[rust png] Roll png
crate to version 0.18*
This CL has been created semi-automatically. Manual changes have been made as follows: * Before automated update: - Switch to 0.18 in `//third_party/rust/chromium_crates_io/Cargo.toml` (`=...` syntax is needed because 0.18 is a "prerelease") - Remove 0.17-targeting patches under `//third_party/rust/chromium_crates_io/patches/png` * After automated update: - Remove old `//third_party/rust/foo/vX` directories - Edit `skia/BUILD.gn` to enable `png_0_18` crate feature (this part depends on http://review.skia.org/958801) - Record the audit in `.../chromium_crates_io/supply-chain/audits.toml` Updated crates: * png: 0.17.16 => 0.18.0-rc Removed crates: * bitflags@1.3.2 Chromium `supply-chain/config.toml` policy requires that the following audit criteria are met (note that these are the *minimum* required criteria and `supply-chain/audits.toml` can and should record a stricter certification if possible; see also //docs/rust-unsafe.md): * png@0.18.0-rc: crypto-safe, safe-to-deploy, ub-risk-2 Bug: None Change-Id: I9008912d7ac58b66887b7bf276367e56aad51828 Cq-Include-Trybots: chromium/try:android-rust-arm32-rel Cq-Include-Trybots: chromium/try:android-rust-arm64-dbg Cq-Include-Trybots: chromium/try:android-rust-arm64-rel Cq-Include-Trybots: chromium/try:linux-rust-x64-dbg Cq-Include-Trybots: chromium/try:linux-rust-x64-rel Cq-Include-Trybots: chromium/try:win-rust-x64-dbg Cq-Include-Trybots: chromium/try:win-rust-x64-rel Disable-Rts: True Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6318699 Reviewed-by: Liza Burakova <liza@chromium.org> Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org> Cr-Commit-Position: refs/heads/main@{#1429744}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
0b14f5ae80
commit
2654c789bc
skia
third_party/rust
chromium_crates_io
Cargo.lockCargo.toml
patches
supply-chain
vendor
bitflags-1.3.2
.cargo_vcs_info.json.gitignoreCHANGELOG.mdCODE_OF_CONDUCT.mdCargo.tomlCargo.toml.origLICENSE-MITREADME.md
.github
workflows
src
tests
basic.rscompile.rs
compile-fail
compile-pass
impls
redefinition
repr
visibility
png-0.17.16
png-0.18.0-rc
png
@ -630,7 +630,8 @@ if (enable_rust_png) {
|
|||||||
sources = skia_codec_rust_png_ffi_rs_srcs
|
sources = skia_codec_rust_png_ffi_rs_srcs
|
||||||
cxx_bindings = skia_codec_rust_png_ffi_cxx_bridge_srcs
|
cxx_bindings = skia_codec_rust_png_ffi_cxx_bridge_srcs
|
||||||
public_deps = [ ":rust_png_ffi_cpp" ]
|
public_deps = [ ":rust_png_ffi_cpp" ]
|
||||||
deps = [ "//third_party/rust/png/v0_17:lib" ]
|
deps = [ "//third_party/rust/png/v0_18:lib" ]
|
||||||
|
features = [ "png_0_18" ]
|
||||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||||
configs += [
|
configs += [
|
||||||
":skia_config",
|
":skia_config",
|
||||||
|
11
third_party/rust/chromium_crates_io/Cargo.lock
generated
vendored
11
third_party/rust/chromium_crates_io/Cargo.lock
generated
vendored
@ -40,11 +40,6 @@ name = "base64"
|
|||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
@ -115,7 +110,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags 2.9.0",
|
"bitflags",
|
||||||
"bstr",
|
"bstr",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -954,10 +949,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.16"
|
version = "0.18.0-rc"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"fdeflate",
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
@ -30,7 +30,7 @@ itertools = "0.11"
|
|||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
nom = "7.1.3"
|
nom = "7.1.3"
|
||||||
png = "0.17"
|
png = "=0.18.0-rc"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
prost = "0.13.3"
|
prost = "0.13.3"
|
||||||
qr_code = "2"
|
qr_code = "2"
|
||||||
|
72
third_party/rust/chromium_crates_io/patches/png/0101-Add-support-for-parsing-eXIf-chunk.patch
vendored
72
third_party/rust/chromium_crates_io/patches/png/0101-Add-support-for-parsing-eXIf-chunk.patch
vendored
@ -1,72 +0,0 @@
|
|||||||
From aa16ef97ab23c52b34c43e9d98d7f3cb56ad35f1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Lukasz Anforowicz <lukasza@chromium.org>
|
|
||||||
Date: Fri, 17 Jan 2025 23:10:45 +0000
|
|
||||||
Subject: [PATCH] Add support for parsing `eXIf` chunk.
|
|
||||||
|
|
||||||
The `eXIf` chunk was already supported in `encoder.rs`, but this commit
|
|
||||||
also adds support to `decoder/stream.rs`. This commit is needed for
|
|
||||||
parity with the existing PNG decoder in Blink / Chromium - see
|
|
||||||
https://crbug.com/390707316
|
|
||||||
---
|
|
||||||
src/decoder/stream.rs | 24 +++++++++++++++++++++++-
|
|
||||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
|
|
||||||
index 1b00968..904d3be 100644
|
|
||||||
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
|
|
||||||
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
|
|
||||||
@@ -989,6 +989,7 @@ impl StreamingDecoder {
|
|
||||||
chunk::cICP => Ok(self.parse_cicp()),
|
|
||||||
chunk::mDCV => Ok(self.parse_mdcv()),
|
|
||||||
chunk::cLLI => Ok(self.parse_clli()),
|
|
||||||
+ chunk::eXIf => Ok(self.parse_exif()),
|
|
||||||
chunk::bKGD => Ok(self.parse_bkgd()),
|
|
||||||
chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
|
|
||||||
chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
|
|
||||||
@@ -1487,6 +1488,16 @@ impl StreamingDecoder {
|
|
||||||
Decoded::Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
+ fn parse_exif(&mut self) -> Decoded {
|
|
||||||
+ // We ignore a second, duplicated eXIf chunk (if any).
|
|
||||||
+ let info = self.info.as_mut().unwrap();
|
|
||||||
+ if info.exif_metadata.is_none() {
|
|
||||||
+ info.exif_metadata = Some(self.current_chunk.raw_bytes.clone().into());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ Decoded::Nothing
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
fn parse_iccp(&mut self) -> Result<Decoded, DecodingError> {
|
|
||||||
if self.have_idat {
|
|
||||||
Err(DecodingError::Format(
|
|
||||||
@@ -2125,7 +2136,7 @@ mod tests {
|
|
||||||
assert!(decoder.read_info().is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
- /// Test handling of `mDCV` and `cLLI` chunks.`
|
|
||||||
+ /// Test handling of `mDCV` and `cLLI` chunks.
|
|
||||||
#[test]
|
|
||||||
fn test_mdcv_and_clli_chunks() {
|
|
||||||
let decoder = crate::Decoder::new(File::open("tests/bugfixes/cicp_pq.png").unwrap());
|
|
||||||
@@ -2155,6 +2166,17 @@ mod tests {
|
|
||||||
assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /// Test handling of `eXIf` chunk.
|
|
||||||
+ #[test]
|
|
||||||
+ fn test_exif_chunk() {
|
|
||||||
+ let decoder =
|
|
||||||
+ crate::Decoder::new(File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap());
|
|
||||||
+ let reader = decoder.read_info().unwrap();
|
|
||||||
+ let info = reader.info();
|
|
||||||
+ let exif = info.exif_metadata.as_ref().unwrap().as_ref();
|
|
||||||
+ assert_eq!(exif.len(), 90);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/// Tests what happens then [`Reader.finish`] is called twice.
|
|
||||||
#[test]
|
|
||||||
fn test_finishing_twice() {
|
|
||||||
--
|
|
||||||
2.48.1.262.g85cc9f2d1e-goog
|
|
||||||
|
|
@ -2210,6 +2210,12 @@ who = "Adrian Taylor <adetaylor@chromium.org>"
|
|||||||
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
|
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
|
||||||
delta = "0.17.15 -> 0.17.16"
|
delta = "0.17.15 -> 0.17.16"
|
||||||
|
|
||||||
|
[[audits.png]]
|
||||||
|
who = "Lukasz Anforowicz <lukasza@chromium.org>"
|
||||||
|
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
|
||||||
|
delta = "0.17.16 -> 0.18.0-rc"
|
||||||
|
notes = "Still no `unsafe`, no cryptography, and justified usage of `std::fs`."
|
||||||
|
|
||||||
[[audits.potential_utf]]
|
[[audits.potential_utf]]
|
||||||
who = "Manish Goregaokar <manishearth@google.com>"
|
who = "Manish Goregaokar <manishearth@google.com>"
|
||||||
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-2"]
|
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-2"]
|
||||||
|
@ -62,9 +62,6 @@ criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
|||||||
[policy."base64:0.22.1"]
|
[policy."base64:0.22.1"]
|
||||||
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
||||||
|
|
||||||
[policy."bitflags:1.3.2"]
|
|
||||||
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
|
||||||
|
|
||||||
[policy."bitflags:2.9.0"]
|
[policy."bitflags:2.9.0"]
|
||||||
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
||||||
|
|
||||||
@ -332,7 +329,7 @@ criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
|||||||
[policy."num-traits:0.2.19"]
|
[policy."num-traits:0.2.19"]
|
||||||
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
||||||
|
|
||||||
[policy."png:0.17.16"]
|
[policy."png:0.18.0-rc"]
|
||||||
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
|
||||||
|
|
||||||
[policy."potential_utf:0.1.0"]
|
[policy."potential_utf:0.1.0"]
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"git": {
|
|
||||||
"sha1": "ed185cfb1c447c1b4bd6ac021c9ec3bb02c9e2f2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
name: Rust
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
rust:
|
|
||||||
- stable
|
|
||||||
- beta
|
|
||||||
- nightly
|
|
||||||
- 1.46.0
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: ${{ matrix.rust }}
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Default features
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --features example_generated
|
|
||||||
|
|
||||||
embedded:
|
|
||||||
name: Build (embedded)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
target: thumbv6m-none-eabi
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Default features
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: build
|
|
||||||
args: -Z avoid-dev-deps --features example_generated --target thumbv6m-none-eabi
|
|
@ -1,5 +0,0 @@
|
|||||||
wip
|
|
||||||
target
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
/.idea/
|
|
@ -1,206 +0,0 @@
|
|||||||
# 1.3.2
|
|
||||||
|
|
||||||
- Allow `non_snake_case` in generated flags types ([#256])
|
|
||||||
|
|
||||||
[#252]: https://github.com/bitflags/bitflags/pull/256
|
|
||||||
|
|
||||||
# 1.3.1
|
|
||||||
|
|
||||||
- Revert unconditional `#[repr(transparent)]` ([#252])
|
|
||||||
|
|
||||||
[#252]: https://github.com/bitflags/bitflags/pull/252
|
|
||||||
|
|
||||||
# 1.3.0 (yanked)
|
|
||||||
|
|
||||||
- Add `#[repr(transparent)]` ([#187])
|
|
||||||
|
|
||||||
- End `empty` doc comment with full stop ([#202])
|
|
||||||
|
|
||||||
- Fix typo in crate root docs ([#206])
|
|
||||||
|
|
||||||
- Document from_bits_unchecked unsafety ([#207])
|
|
||||||
|
|
||||||
- Let `is_all` ignore extra bits ([#211])
|
|
||||||
|
|
||||||
- Allows empty flag definition ([#225])
|
|
||||||
|
|
||||||
- Making crate accessible from std ([#227])
|
|
||||||
|
|
||||||
- Make `from_bits` a const fn ([#229])
|
|
||||||
|
|
||||||
- Allow multiple bitflags structs in one macro invocation ([#235])
|
|
||||||
|
|
||||||
- Add named functions to perform set operations ([#244])
|
|
||||||
|
|
||||||
- Fix typos in method docs ([#245])
|
|
||||||
|
|
||||||
- Modernization of the `bitflags` macro to take advantage of newer features and 2018 idioms ([#246])
|
|
||||||
|
|
||||||
- Fix regression (in an unreleased feature) and simplify tests ([#247])
|
|
||||||
|
|
||||||
- Use `Self` and fix bug when overriding `stringify!` ([#249])
|
|
||||||
|
|
||||||
[#187]: https://github.com/bitflags/bitflags/pull/187
|
|
||||||
[#202]: https://github.com/bitflags/bitflags/pull/202
|
|
||||||
[#206]: https://github.com/bitflags/bitflags/pull/206
|
|
||||||
[#207]: https://github.com/bitflags/bitflags/pull/207
|
|
||||||
[#211]: https://github.com/bitflags/bitflags/pull/211
|
|
||||||
[#225]: https://github.com/bitflags/bitflags/pull/225
|
|
||||||
[#227]: https://github.com/bitflags/bitflags/pull/227
|
|
||||||
[#229]: https://github.com/bitflags/bitflags/pull/229
|
|
||||||
[#235]: https://github.com/bitflags/bitflags/pull/235
|
|
||||||
[#244]: https://github.com/bitflags/bitflags/pull/244
|
|
||||||
[#245]: https://github.com/bitflags/bitflags/pull/245
|
|
||||||
[#246]: https://github.com/bitflags/bitflags/pull/246
|
|
||||||
[#247]: https://github.com/bitflags/bitflags/pull/247
|
|
||||||
[#249]: https://github.com/bitflags/bitflags/pull/249
|
|
||||||
|
|
||||||
# 1.2.1
|
|
||||||
|
|
||||||
- Remove extraneous `#[inline]` attributes ([#194])
|
|
||||||
|
|
||||||
[#194]: https://github.com/bitflags/bitflags/pull/194
|
|
||||||
|
|
||||||
# 1.2.0
|
|
||||||
|
|
||||||
- Fix typo: {Lower, Upper}Exp - {Lower, Upper}Hex ([#183])
|
|
||||||
|
|
||||||
- Add support for "unknown" bits ([#188])
|
|
||||||
|
|
||||||
[#183]: https://github.com/rust-lang-nursery/bitflags/pull/183
|
|
||||||
[#188]: https://github.com/rust-lang-nursery/bitflags/pull/188
|
|
||||||
|
|
||||||
# 1.1.0
|
|
||||||
|
|
||||||
This is a re-release of `1.0.5`, which was yanked due to a bug in the RLS.
|
|
||||||
|
|
||||||
# 1.0.5
|
|
||||||
|
|
||||||
- Use compiletest_rs flags supported by stable toolchain ([#171])
|
|
||||||
|
|
||||||
- Put the user provided attributes first ([#173])
|
|
||||||
|
|
||||||
- Make bitflags methods `const` on newer compilers ([#175])
|
|
||||||
|
|
||||||
[#171]: https://github.com/rust-lang-nursery/bitflags/pull/171
|
|
||||||
[#173]: https://github.com/rust-lang-nursery/bitflags/pull/173
|
|
||||||
[#175]: https://github.com/rust-lang-nursery/bitflags/pull/175
|
|
||||||
|
|
||||||
# 1.0.4
|
|
||||||
|
|
||||||
- Support Rust 2018 style macro imports ([#165])
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use bitflags::bitflags;
|
|
||||||
```
|
|
||||||
|
|
||||||
[#165]: https://github.com/rust-lang-nursery/bitflags/pull/165
|
|
||||||
|
|
||||||
# 1.0.3
|
|
||||||
|
|
||||||
- Improve zero value flag handling and documentation ([#157])
|
|
||||||
|
|
||||||
[#157]: https://github.com/rust-lang-nursery/bitflags/pull/157
|
|
||||||
|
|
||||||
# 1.0.2
|
|
||||||
|
|
||||||
- 30% improvement in compile time of bitflags crate ([#156])
|
|
||||||
|
|
||||||
- Documentation improvements ([#153])
|
|
||||||
|
|
||||||
- Implementation cleanup ([#149])
|
|
||||||
|
|
||||||
[#156]: https://github.com/rust-lang-nursery/bitflags/pull/156
|
|
||||||
[#153]: https://github.com/rust-lang-nursery/bitflags/pull/153
|
|
||||||
[#149]: https://github.com/rust-lang-nursery/bitflags/pull/149
|
|
||||||
|
|
||||||
# 1.0.1
|
|
||||||
- Add support for `pub(restricted)` specifier on the bitflags struct ([#135])
|
|
||||||
- Optimize performance of `all()` when called from a separate crate ([#136])
|
|
||||||
|
|
||||||
[#135]: https://github.com/rust-lang-nursery/bitflags/pull/135
|
|
||||||
[#136]: https://github.com/rust-lang-nursery/bitflags/pull/136
|
|
||||||
|
|
||||||
# 1.0.0
|
|
||||||
- **[breaking change]** Macro now generates [associated constants](https://doc.rust-lang.org/reference/items.html#associated-constants) ([#24])
|
|
||||||
|
|
||||||
- **[breaking change]** Minimum supported version is Rust **1.20**, due to usage of associated constants
|
|
||||||
|
|
||||||
- After being broken in 0.9, the `#[deprecated]` attribute is now supported again ([#112])
|
|
||||||
|
|
||||||
- Other improvements to unit tests and documentation ([#106] and [#115])
|
|
||||||
|
|
||||||
[#24]: https://github.com/rust-lang-nursery/bitflags/pull/24
|
|
||||||
[#106]: https://github.com/rust-lang-nursery/bitflags/pull/106
|
|
||||||
[#112]: https://github.com/rust-lang-nursery/bitflags/pull/112
|
|
||||||
[#115]: https://github.com/rust-lang-nursery/bitflags/pull/115
|
|
||||||
|
|
||||||
## How to update your code to use associated constants
|
|
||||||
Assuming the following structure definition:
|
|
||||||
```rust
|
|
||||||
bitflags! {
|
|
||||||
struct Something: u8 {
|
|
||||||
const FOO = 0b01,
|
|
||||||
const BAR = 0b10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
In 0.9 and older you could do:
|
|
||||||
```rust
|
|
||||||
let x = FOO.bits | BAR.bits;
|
|
||||||
```
|
|
||||||
Now you must use:
|
|
||||||
```rust
|
|
||||||
let x = Something::FOO.bits | Something::BAR.bits;
|
|
||||||
```
|
|
||||||
|
|
||||||
# 0.9.1
|
|
||||||
- Fix the implementation of `Formatting` traits when other formatting traits were present in scope ([#105])
|
|
||||||
|
|
||||||
[#105]: https://github.com/rust-lang-nursery/bitflags/pull/105
|
|
||||||
|
|
||||||
# 0.9.0
|
|
||||||
- **[breaking change]** Use struct keyword instead of flags to define bitflag types ([#84])
|
|
||||||
|
|
||||||
- **[breaking change]** Terminate const items with semicolons instead of commas ([#87])
|
|
||||||
|
|
||||||
- Implement the `Hex`, `Octal`, and `Binary` formatting traits ([#86])
|
|
||||||
|
|
||||||
- Printing an empty flag value with the `Debug` trait now prints "(empty)" instead of nothing ([#85])
|
|
||||||
|
|
||||||
- The `bitflags!` macro can now be used inside of a fn body, to define a type local to that function ([#74])
|
|
||||||
|
|
||||||
[#74]: https://github.com/rust-lang-nursery/bitflags/pull/74
|
|
||||||
[#84]: https://github.com/rust-lang-nursery/bitflags/pull/84
|
|
||||||
[#85]: https://github.com/rust-lang-nursery/bitflags/pull/85
|
|
||||||
[#86]: https://github.com/rust-lang-nursery/bitflags/pull/86
|
|
||||||
[#87]: https://github.com/rust-lang-nursery/bitflags/pull/87
|
|
||||||
|
|
||||||
# 0.8.2
|
|
||||||
- Update feature flag used when building bitflags as a dependency of the Rust toolchain
|
|
||||||
|
|
||||||
# 0.8.1
|
|
||||||
- Allow bitflags to be used as a dependency of the Rust toolchain
|
|
||||||
|
|
||||||
# 0.8.0
|
|
||||||
- Add support for the experimental `i128` and `u128` integer types ([#57])
|
|
||||||
- Add set method: `flags.set(SOME_FLAG, true)` or `flags.set(SOME_FLAG, false)` ([#55])
|
|
||||||
This may break code that defines its own set method
|
|
||||||
|
|
||||||
[#55]: https://github.com/rust-lang-nursery/bitflags/pull/55
|
|
||||||
[#57]: https://github.com/rust-lang-nursery/bitflags/pull/57
|
|
||||||
|
|
||||||
# 0.7.1
|
|
||||||
*(yanked)*
|
|
||||||
|
|
||||||
# 0.7.0
|
|
||||||
- Implement the Extend trait ([#49])
|
|
||||||
- Allow definitions inside the `bitflags!` macro to refer to items imported from other modules ([#51])
|
|
||||||
|
|
||||||
[#49]: https://github.com/rust-lang-nursery/bitflags/pull/49
|
|
||||||
[#51]: https://github.com/rust-lang-nursery/bitflags/pull/51
|
|
||||||
|
|
||||||
# 0.6.0
|
|
||||||
- The `no_std` feature was removed as it is now the default
|
|
||||||
- The `assignment_operators` feature was remove as it is now enabled by default
|
|
||||||
- Some clippy suggestions have been applied
|
|
@ -1,73 +0,0 @@
|
|||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
In the interest of fostering an open and welcoming environment, we as
|
|
||||||
contributors and maintainers pledge to making participation in our project and
|
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
||||||
education, socio-economic status, nationality, personal appearance, race,
|
|
||||||
religion, or sexual identity and orientation.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment
|
|
||||||
include:
|
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
|
||||||
* Being respectful of differing viewpoints and experiences
|
|
||||||
* Gracefully accepting constructive criticism
|
|
||||||
* Focusing on what is best for the community
|
|
||||||
* Showing empathy towards other community members
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
||||||
advances
|
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or electronic
|
|
||||||
address, without explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Our Responsibilities
|
|
||||||
|
|
||||||
Project maintainers are responsible for clarifying the standards of acceptable
|
|
||||||
behavior and are expected to take appropriate and fair corrective action in
|
|
||||||
response to any instances of unacceptable behavior.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or
|
|
||||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
||||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
||||||
permanently any contributor for other behaviors that they deem inappropriate,
|
|
||||||
threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community. Examples of
|
|
||||||
representing a project or community include using an official project e-mail
|
|
||||||
address, posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event. Representation of a project may be
|
|
||||||
further defined and clarified by project maintainers.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported by contacting the project team at coc@senaite.org. All
|
|
||||||
complaints will be reviewed and investigated and will result in a response that
|
|
||||||
is deemed necessary and appropriate to the circumstances. The project team is
|
|
||||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
||||||
Further details of specific enforcement policies may be posted separately.
|
|
||||||
|
|
||||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
||||||
faith may face temporary or permanent repercussions as determined by other
|
|
||||||
members of the project's leadership.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
||||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
@ -1,58 +0,0 @@
|
|||||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
||||||
#
|
|
||||||
# When uploading crates to the registry Cargo will automatically
|
|
||||||
# "normalize" Cargo.toml files for maximal compatibility
|
|
||||||
# with all versions of Cargo and also rewrite `path` dependencies
|
|
||||||
# to registry (e.g., crates.io) dependencies
|
|
||||||
#
|
|
||||||
# If you believe there's an error in this file please file an
|
|
||||||
# issue against the rust-lang/cargo repository. If you're
|
|
||||||
# editing this file be aware that the upstream Cargo.toml
|
|
||||||
# will likely look very different (and much more reasonable)
|
|
||||||
|
|
||||||
[package]
|
|
||||||
edition = "2018"
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
authors = ["The Rust Project Developers"]
|
|
||||||
exclude = ["bors.toml"]
|
|
||||||
description = "A macro to generate structures which behave like bitflags.\n"
|
|
||||||
homepage = "https://github.com/bitflags/bitflags"
|
|
||||||
documentation = "https://docs.rs/bitflags"
|
|
||||||
readme = "README.md"
|
|
||||||
keywords = ["bit", "bitmask", "bitflags", "flags"]
|
|
||||||
categories = ["no-std"]
|
|
||||||
license = "MIT/Apache-2.0"
|
|
||||||
repository = "https://github.com/bitflags/bitflags"
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["example_generated"]
|
|
||||||
[dependencies.compiler_builtins]
|
|
||||||
version = "0.1.2"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.core]
|
|
||||||
version = "1.0.0"
|
|
||||||
optional = true
|
|
||||||
package = "rustc-std-workspace-core"
|
|
||||||
[dev-dependencies.rustversion]
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
[dev-dependencies.serde]
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
[dev-dependencies.serde_derive]
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
[dev-dependencies.serde_json]
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
[dev-dependencies.trybuild]
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
[dev-dependencies.walkdir]
|
|
||||||
version = "2.3"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
example_generated = []
|
|
||||||
rustc-dep-of-std = ["core", "compiler_builtins"]
|
|
39
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/Cargo.toml.orig
generated
vendored
39
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/Cargo.toml.orig
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "bitflags"
|
|
||||||
# NB: When modifying, also modify:
|
|
||||||
# 1. html_root_url in lib.rs
|
|
||||||
# 2. number in readme (for breaking changes)
|
|
||||||
version = "1.3.2"
|
|
||||||
edition = "2018"
|
|
||||||
authors = ["The Rust Project Developers"]
|
|
||||||
license = "MIT/Apache-2.0"
|
|
||||||
keywords = ["bit", "bitmask", "bitflags", "flags"]
|
|
||||||
readme = "README.md"
|
|
||||||
repository = "https://github.com/bitflags/bitflags"
|
|
||||||
homepage = "https://github.com/bitflags/bitflags"
|
|
||||||
documentation = "https://docs.rs/bitflags"
|
|
||||||
categories = ["no-std"]
|
|
||||||
description = """
|
|
||||||
A macro to generate structures which behave like bitflags.
|
|
||||||
"""
|
|
||||||
exclude = ["bors.toml"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' }
|
|
||||||
compiler_builtins = { version = '0.1.2', optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
trybuild = "1.0"
|
|
||||||
rustversion = "1.0"
|
|
||||||
walkdir = "2.3"
|
|
||||||
serde = "1.0"
|
|
||||||
serde_derive = "1.0"
|
|
||||||
serde_json = "1.0"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
example_generated = []
|
|
||||||
rustc-dep-of-std = ["core", "compiler_builtins"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["example_generated"]
|
|
@ -1,25 +0,0 @@
|
|||||||
Copyright (c) 2014 The Rust Project Developers
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without
|
|
||||||
limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
@ -1,32 +0,0 @@
|
|||||||
bitflags
|
|
||||||
========
|
|
||||||
|
|
||||||
[](https://github.com/bitflags/bitflags/actions)
|
|
||||||
[](https://gitter.im/bitflags/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
|
|
||||||
[](https://crates.io/crates/bitflags)
|
|
||||||
[](https://docs.rs/bitflags)
|
|
||||||

|
|
||||||
|
|
||||||
A Rust macro to generate structures which behave like a set of bitflags
|
|
||||||
|
|
||||||
- [Documentation](https://docs.rs/bitflags)
|
|
||||||
- [Release notes](https://github.com/bitflags/bitflags/releases)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Add this to your `Cargo.toml`:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[dependencies]
|
|
||||||
bitflags = "1.3"
|
|
||||||
```
|
|
||||||
|
|
||||||
and this to your source code:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use bitflags::bitflags;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Rust Version Support
|
|
||||||
|
|
||||||
The minimum supported Rust version is 1.46 due to use of associated constants and const functions.
|
|
@ -1,14 +0,0 @@
|
|||||||
//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS
|
|
||||||
//! CRATE**.
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
|
|
||||||
/// Note that this struct is just for documentation purposes only, it must not be used outside
|
|
||||||
/// this crate.
|
|
||||||
pub struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
const B = 0b00000010;
|
|
||||||
const C = 0b00000100;
|
|
||||||
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// baz
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
#[doc = "bar"]
|
|
||||||
const B = 0b00000010;
|
|
||||||
const C = 0b00000100;
|
|
||||||
#[doc = "foo"]
|
|
||||||
const ABC = Flags::A.bits | Flags::B.bits | Flags::C.bits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn basic() {
|
|
||||||
assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C);
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
*.stderr
|
|
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/copy.rs
vendored
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/copy.rs
vendored
@ -1,10 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
27
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/copy.stderr.beta
vendored
27
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/copy.stderr.beta
vendored
@ -1,27 +0,0 @@
|
|||||||
error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Flags`
|
|
||||||
--> $DIR/copy.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(Clone, Copy)]
|
|
||||||
| | ----- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `Flags`
|
|
||||||
--> $DIR/copy.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(Clone, Copy)]
|
|
||||||
| | ---- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/eq.rs
vendored
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/eq.rs
vendored
@ -1,10 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
55
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/eq.stderr.beta
vendored
55
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/impls/eq.stderr.beta
vendored
@ -1,55 +0,0 @@
|
|||||||
error[E0119]: conflicting implementations of trait `std::cmp::PartialEq` for type `Flags`
|
|
||||||
--> $DIR/eq.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(PartialEq, Eq)]
|
|
||||||
| | --------- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `std::cmp::Eq` for type `Flags`
|
|
||||||
--> $DIR/eq.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(PartialEq, Eq)]
|
|
||||||
| | -- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `std::marker::StructuralPartialEq` for type `Flags`
|
|
||||||
--> $DIR/eq.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(PartialEq, Eq)]
|
|
||||||
| | --------- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `std::marker::StructuralEq` for type `Flags`
|
|
||||||
--> $DIR/eq.rs:3:1
|
|
||||||
|
|
|
||||||
3 | / bitflags! {
|
|
||||||
4 | | #[derive(PartialEq, Eq)]
|
|
||||||
| | -- first implementation here
|
|
||||||
5 | | struct Flags: u32 {
|
|
||||||
6 | | const A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
8 | | }
|
|
||||||
| |_^ conflicting implementation for `Flags`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
123
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/non_integer_base/all_defined.rs
vendored
123
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/non_integer_base/all_defined.rs
vendored
@ -1,123 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fmt::{
|
|
||||||
self,
|
|
||||||
Debug,
|
|
||||||
Display,
|
|
||||||
LowerHex,
|
|
||||||
UpperHex,
|
|
||||||
Octal,
|
|
||||||
Binary,
|
|
||||||
},
|
|
||||||
ops::{
|
|
||||||
BitAnd,
|
|
||||||
BitOr,
|
|
||||||
BitXor,
|
|
||||||
BitAndAssign,
|
|
||||||
BitOrAssign,
|
|
||||||
BitXorAssign,
|
|
||||||
Not,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
// Ideally we'd actually want this to work, but currently need something like `num`'s `Zero`
|
|
||||||
// With some design work it could be made possible
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
struct MyInt(u8);
|
|
||||||
|
|
||||||
impl BitAnd for MyInt {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn bitand(self, other: Self) -> Self {
|
|
||||||
MyInt(self.0 & other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOr for MyInt {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn bitor(self, other: Self) -> Self {
|
|
||||||
MyInt(self.0 | other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitXor for MyInt {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn bitxor(self, other: Self) -> Self {
|
|
||||||
MyInt(self.0 ^ other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAndAssign for MyInt {
|
|
||||||
fn bitand_assign(&mut self, other: Self) {
|
|
||||||
self.0 &= other.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOrAssign for MyInt {
|
|
||||||
fn bitor_assign(&mut self, other: Self) {
|
|
||||||
self.0 |= other.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitXorAssign for MyInt {
|
|
||||||
fn bitxor_assign(&mut self, other: Self) {
|
|
||||||
self.0 ^= other.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Debug::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Display::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LowerHex for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
LowerHex::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UpperHex for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
UpperHex::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Octal for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Octal::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Binary for MyInt {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Binary::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Not for MyInt {
|
|
||||||
type Output = MyInt;
|
|
||||||
|
|
||||||
fn not(self) -> Self {
|
|
||||||
MyInt(!self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Flags128: MyInt {
|
|
||||||
const A = MyInt(0b0000_0001u8);
|
|
||||||
const B = MyInt(0b0000_0010u8);
|
|
||||||
const C = MyInt(0b0000_0100u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,27 +0,0 @@
|
|||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/all_defined.rs:115:1
|
|
||||||
|
|
|
||||||
115 | / bitflags! {
|
|
||||||
116 | | struct Flags128: MyInt {
|
|
||||||
117 | | const A = MyInt(0b0000_0001u8);
|
|
||||||
118 | | const B = MyInt(0b0000_0010u8);
|
|
||||||
119 | | const C = MyInt(0b0000_0100u8);
|
|
||||||
120 | | }
|
|
||||||
121 | | }
|
|
||||||
| |_^ expected struct `MyInt`, found integer
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `__impl_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/all_defined.rs:115:1
|
|
||||||
|
|
|
||||||
115 | / bitflags! {
|
|
||||||
116 | | struct Flags128: MyInt {
|
|
||||||
117 | | const A = MyInt(0b0000_0001u8);
|
|
||||||
118 | | const B = MyInt(0b0000_0010u8);
|
|
||||||
119 | | const C = MyInt(0b0000_0100u8);
|
|
||||||
120 | | }
|
|
||||||
121 | | }
|
|
||||||
| |_^ expected struct `MyInt`, found integer
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
13
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/non_integer_base/all_missing.rs
vendored
13
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/non_integer_base/all_missing.rs
vendored
@ -1,13 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
struct MyInt(u8);
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Flags128: MyInt {
|
|
||||||
const A = MyInt(0b0000_0001);
|
|
||||||
const B = MyInt(0b0000_0010);
|
|
||||||
const C = MyInt(0b0000_0100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,13 +0,0 @@
|
|||||||
error[E0204]: the trait `Copy` may not be implemented for this type
|
|
||||||
--> $DIR/all_missing.rs:5:1
|
|
||||||
|
|
|
||||||
5 | / bitflags! {
|
|
||||||
6 | | struct Flags128: MyInt {
|
|
||||||
7 | | const A = MyInt(0b0000_0001);
|
|
||||||
8 | | const B = MyInt(0b0000_0010);
|
|
||||||
9 | | const C = MyInt(0b0000_0100);
|
|
||||||
10 | | }
|
|
||||||
11 | | }
|
|
||||||
| |_^ this field does not implement `Copy`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
13
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/private_field.rs
vendored
13
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/private_field.rs
vendored
@ -1,13 +0,0 @@
|
|||||||
mod example {
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct Flags1: u32 {
|
|
||||||
const FLAG_A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let flag1 = example::Flags1::FLAG_A.bits;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
error[E0616]: field `bits` of struct `Flags1` is private
|
|
||||||
--> $DIR/private_field.rs:12:41
|
|
||||||
|
|
|
||||||
12 | let flag1 = example::Flags1::FLAG_A.bits;
|
|
||||||
| ^^^^ private field
|
|
||||||
|
|
|
||||||
help: a method `bits` also exists, call it with parentheses
|
|
||||||
|
|
|
||||||
12 | let flag1 = example::Flags1::FLAG_A.bits();
|
|
||||||
| ^^
|
|
18
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/private_flags.rs
vendored
18
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/private_flags.rs
vendored
@ -1,18 +0,0 @@
|
|||||||
mod example {
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct Flags1: u32 {
|
|
||||||
const FLAG_A = 0b00000001;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Flags2: u32 {
|
|
||||||
const FLAG_B = 0b00000010;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let flag1 = example::Flags1::FLAG_A;
|
|
||||||
let flag2 = example::Flags2::FLAG_B;
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
error[E0603]: struct `Flags2` is private
|
|
||||||
--> $DIR/private_flags.rs:17:26
|
|
||||||
|
|
|
||||||
17 | let flag2 = example::Flags2::FLAG_B;
|
|
||||||
| ^^^^^^ private struct
|
|
||||||
|
|
|
||||||
note: the struct `Flags2` is defined here
|
|
||||||
--> $DIR/private_flags.rs:4:5
|
|
||||||
|
|
|
||||||
4 | / bitflags! {
|
|
||||||
5 | | pub struct Flags1: u32 {
|
|
||||||
6 | | const FLAG_A = 0b00000001;
|
|
||||||
7 | | }
|
|
||||||
... |
|
|
||||||
11 | | }
|
|
||||||
12 | | }
|
|
||||||
| |_____^
|
|
||||||
= note: this error originates in the macro `bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
9
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/pub_const.rs
vendored
9
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-fail/visibility/pub_const.rs
vendored
@ -1,9 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct Flags1: u32 {
|
|
||||||
pub const FLAG_A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,5 +0,0 @@
|
|||||||
error: no rules expected the token `pub`
|
|
||||||
--> $DIR/pub_const.rs:5:9
|
|
||||||
|
|
|
||||||
5 | pub const FLAG_A = 0b00000001;
|
|
||||||
| ^^^ no rules expected this token in macro call
|
|
17
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/convert.rs
vendored
17
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/convert.rs
vendored
@ -1,17 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u32> for Flags {
|
|
||||||
fn from(v: u32) -> Flags {
|
|
||||||
Flags::from_bits_truncate(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/default.rs
vendored
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/default.rs
vendored
@ -1,10 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[derive(Default)]
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
15
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/inherent_methods.rs
vendored
15
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/impls/inherent_methods.rs
vendored
@ -1,15 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Flags {
|
|
||||||
pub fn new() -> Flags {
|
|
||||||
Flags::A
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
14
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/redefinition/core.rs
vendored
14
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/redefinition/core.rs
vendored
@ -1,14 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
// Checks for possible errors caused by overriding names used by `bitflags!` internally.
|
|
||||||
|
|
||||||
mod core {}
|
|
||||||
mod _core {}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Test: u8 {
|
|
||||||
const A = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
19
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/redefinition/stringify.rs
vendored
19
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/redefinition/stringify.rs
vendored
@ -1,19 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
// Checks for possible errors caused by overriding names used by `bitflags!` internally.
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! stringify {
|
|
||||||
($($t:tt)*) => { "..." };
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
struct Test: u8 {
|
|
||||||
const A = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// Just make sure we don't call the redefined `stringify` macro
|
|
||||||
assert_eq!(format!("{:?}", Test::A), "A");
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[repr(C)]
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/repr/transparent.rs
vendored
10
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/repr/transparent.rs
vendored
@ -1,10 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[repr(transparent)]
|
|
||||||
struct Flags: u32 {
|
|
||||||
const A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
11
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/visibility/bits_field.rs
vendored
11
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/visibility/bits_field.rs
vendored
@ -1,11 +0,0 @@
|
|||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct Flags1: u32 {
|
|
||||||
const FLAG_A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
assert_eq!(0b00000001, Flags1::FLAG_A.bits);
|
|
||||||
}
|
|
19
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/visibility/pub_in.rs
vendored
19
third_party/rust/chromium_crates_io/vendor/bitflags-1.3.2/tests/compile-pass/visibility/pub_in.rs
vendored
@ -1,19 +0,0 @@
|
|||||||
mod a {
|
|
||||||
mod b {
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub(in crate::a) struct Flags: u32 {
|
|
||||||
const FLAG_A = 0b00000001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flags() -> u32 {
|
|
||||||
b::Flags::FLAG_A.bits()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
assert_eq!(0b00000001, a::flags());
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fs,
|
|
||||||
ffi::OsStr,
|
|
||||||
io,
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn fail() {
|
|
||||||
prepare_stderr_files("tests/compile-fail").unwrap();
|
|
||||||
|
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.compile_fail("tests/compile-fail/**/*.rs");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn pass() {
|
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.pass("tests/compile-pass/**/*.rs");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compiler messages may change between versions
|
|
||||||
// We don't want to have to track these too closely for `bitflags`, but
|
|
||||||
// having some message to check makes sure user-facing errors are sensical.
|
|
||||||
//
|
|
||||||
// The approach we use is to run the test on all compilers, but only check stderr
|
|
||||||
// output on beta (which is the next stable release). We do this by default ignoring
|
|
||||||
// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files
|
|
||||||
// when we happen to be running on a beta compiler.
|
|
||||||
fn prepare_stderr_files(path: impl AsRef<Path>) -> io::Result<()> {
|
|
||||||
for entry in WalkDir::new(path) {
|
|
||||||
let entry = entry?;
|
|
||||||
|
|
||||||
if entry.path().extension().and_then(OsStr::to_str) == Some("beta") {
|
|
||||||
let renamed = entry.path().with_extension("");
|
|
||||||
|
|
||||||
// Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta`
|
|
||||||
// file if it exists. On `beta` compilers, we'll recreate it. On other compilers,
|
|
||||||
// we don't want to end up checking it anyways.
|
|
||||||
if renamed.exists() {
|
|
||||||
fs::remove_file(&renamed)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
rename_beta_stderr(entry.path(), renamed)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustversion::beta]
|
|
||||||
fn rename_beta_stderr(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
|
|
||||||
fs::copy(from, to)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustversion::not(beta)]
|
|
||||||
fn rename_beta_stderr(_: impl AsRef<Path>, _: impl AsRef<Path>) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
{"files":{}}
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"git": {
|
|
||||||
"sha1": "fbf256669ff23594bf4c618b61fde6a52b79e088"
|
|
||||||
},
|
|
||||||
"path_in_vcs": ""
|
|
||||||
}
|
|
2202
third_party/rust/chromium_crates_io/vendor/png-0.17.16/Cargo.lock
generated
vendored
2202
third_party/rust/chromium_crates_io/vendor/png-0.17.16/Cargo.lock
generated
vendored
File diff suppressed because it is too large
Load Diff
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
@ -1,198 +0,0 @@
|
|||||||
use glium::{
|
|
||||||
backend::glutin::Display,
|
|
||||||
glutin::{
|
|
||||||
self, dpi,
|
|
||||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
|
||||||
event_loop::ControlFlow,
|
|
||||||
},
|
|
||||||
texture::{ClientFormat, RawImage2d},
|
|
||||||
BlitTarget, Rect, Surface,
|
|
||||||
};
|
|
||||||
use std::{borrow::Cow, env, fs::File, io, path};
|
|
||||||
|
|
||||||
/// Load the image using `png`
|
|
||||||
fn load_image(path: &path::PathBuf) -> io::Result<RawImage2d<'static, u8>> {
|
|
||||||
use png::ColorType::*;
|
|
||||||
let mut decoder = png::Decoder::new(File::open(path)?);
|
|
||||||
decoder.set_transformations(png::Transformations::normalize_to_color8());
|
|
||||||
let mut reader = decoder.read_info()?;
|
|
||||||
let mut img_data = vec![0; reader.output_buffer_size()];
|
|
||||||
let info = reader.next_frame(&mut img_data)?;
|
|
||||||
|
|
||||||
let (data, format) = match info.color_type {
|
|
||||||
Rgb => (img_data, ClientFormat::U8U8U8),
|
|
||||||
Rgba => (img_data, ClientFormat::U8U8U8U8),
|
|
||||||
Grayscale => (
|
|
||||||
{
|
|
||||||
let mut vec = Vec::with_capacity(img_data.len() * 3);
|
|
||||||
for g in img_data {
|
|
||||||
vec.extend([g, g, g].iter().cloned())
|
|
||||||
}
|
|
||||||
vec
|
|
||||||
},
|
|
||||||
ClientFormat::U8U8U8,
|
|
||||||
),
|
|
||||||
GrayscaleAlpha => (
|
|
||||||
{
|
|
||||||
let mut vec = Vec::with_capacity(img_data.len() * 3);
|
|
||||||
for ga in img_data.chunks(2) {
|
|
||||||
let g = ga[0];
|
|
||||||
let a = ga[1];
|
|
||||||
vec.extend([g, g, g, a].iter().cloned())
|
|
||||||
}
|
|
||||||
vec
|
|
||||||
},
|
|
||||||
ClientFormat::U8U8U8U8,
|
|
||||||
),
|
|
||||||
_ => unreachable!("uncovered color type"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(RawImage2d {
|
|
||||||
data: Cow::Owned(data),
|
|
||||||
width: info.width,
|
|
||||||
height: info.height,
|
|
||||||
format,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main_loop(files: Vec<path::PathBuf>) -> io::Result<()> {
|
|
||||||
let mut files = files.into_iter();
|
|
||||||
let image = load_image(&files.next().unwrap())?;
|
|
||||||
|
|
||||||
let event_loop = glutin::event_loop::EventLoop::new();
|
|
||||||
let window_builder = glutin::window::WindowBuilder::new().with_title("Show Example");
|
|
||||||
let context_builder = glutin::ContextBuilder::new().with_vsync(true);
|
|
||||||
let display = glium::Display::new(window_builder, context_builder, &event_loop)
|
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
|
|
||||||
resize_window(&display, &image);
|
|
||||||
let mut texture = glium::Texture2d::new(&display, image).unwrap();
|
|
||||||
draw(&display, &texture);
|
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| match event {
|
|
||||||
Event::WindowEvent {
|
|
||||||
event: WindowEvent::CloseRequested,
|
|
||||||
..
|
|
||||||
} => exit(control_flow),
|
|
||||||
Event::WindowEvent {
|
|
||||||
event:
|
|
||||||
WindowEvent::KeyboardInput {
|
|
||||||
input:
|
|
||||||
KeyboardInput {
|
|
||||||
state: ElementState::Pressed,
|
|
||||||
virtual_keycode: code,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
} => match code {
|
|
||||||
Some(VirtualKeyCode::Escape) => exit(control_flow),
|
|
||||||
Some(VirtualKeyCode::Right) => match &files.next() {
|
|
||||||
Some(path) => {
|
|
||||||
match load_image(path) {
|
|
||||||
Ok(image) => {
|
|
||||||
resize_window(&display, &image);
|
|
||||||
texture = glium::Texture2d::new(&display, image).unwrap();
|
|
||||||
draw(&display, &texture);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
println!("Error: {}", err);
|
|
||||||
exit(control_flow);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
None => exit(control_flow),
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
Event::RedrawRequested(_) => draw(&display, &texture),
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw(display: &glium::Display, texture: &glium::Texture2d) {
|
|
||||||
let frame = display.draw();
|
|
||||||
fill_v_flipped(
|
|
||||||
&texture.as_surface(),
|
|
||||||
&frame,
|
|
||||||
glium::uniforms::MagnifySamplerFilter::Linear,
|
|
||||||
);
|
|
||||||
frame.finish().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exit(control_flow: &mut ControlFlow) {
|
|
||||||
*control_flow = ControlFlow::Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_v_flipped<S1, S2>(src: &S1, target: &S2, filter: glium::uniforms::MagnifySamplerFilter)
|
|
||||||
where
|
|
||||||
S1: Surface,
|
|
||||||
S2: Surface,
|
|
||||||
{
|
|
||||||
let src_dim = src.get_dimensions();
|
|
||||||
let src_rect = Rect {
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
width: src_dim.0,
|
|
||||||
height: src_dim.1,
|
|
||||||
};
|
|
||||||
let target_dim = target.get_dimensions();
|
|
||||||
let target_rect = BlitTarget {
|
|
||||||
left: 0,
|
|
||||||
bottom: target_dim.1,
|
|
||||||
width: target_dim.0 as i32,
|
|
||||||
height: -(target_dim.1 as i32),
|
|
||||||
};
|
|
||||||
src.blit_color(&src_rect, target, &target_rect, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize_window(display: &Display, image: &RawImage2d<'static, u8>) {
|
|
||||||
let mut width = image.width;
|
|
||||||
let mut height = image.height;
|
|
||||||
if width < 50 && height < 50 {
|
|
||||||
width *= 10;
|
|
||||||
height *= 10;
|
|
||||||
}
|
|
||||||
display
|
|
||||||
.gl_window()
|
|
||||||
.window()
|
|
||||||
.set_inner_size(dpi::LogicalSize::new(f64::from(width), f64::from(height)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
if args.len() < 2 {
|
|
||||||
println!("Usage: show files [...]");
|
|
||||||
} else {
|
|
||||||
let mut files = vec![];
|
|
||||||
for file in args.iter().skip(1) {
|
|
||||||
match if file.contains('*') {
|
|
||||||
(|| -> io::Result<_> {
|
|
||||||
for entry in glob::glob(file)
|
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err.msg))?
|
|
||||||
{
|
|
||||||
files.push(
|
|
||||||
entry
|
|
||||||
.map_err(|_| io::Error::new(io::ErrorKind::Other, "glob error"))?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})()
|
|
||||||
} else {
|
|
||||||
files.push(path::PathBuf::from(file));
|
|
||||||
Ok(())
|
|
||||||
} {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) => {
|
|
||||||
println!("{}: {}", file, err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// "tests/pngsuite/pngsuite.png"
|
|
||||||
match main_loop(files) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) => println!("Error: {}", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
6
third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/.cargo_vcs_info.json
vendored
Normal file
6
third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/.cargo_vcs_info.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"git": {
|
||||||
|
"sha1": "eb9b5d7f371b88f15aaca6a8d21c58b86c400d76"
|
||||||
|
},
|
||||||
|
"path_in_vcs": ""
|
||||||
|
}
|
@ -1,3 +1,30 @@
|
|||||||
|
## 0.18.0
|
||||||
|
|
||||||
|
### API Breaking Changes
|
||||||
|
|
||||||
|
* Removed deprecated `Info::encode` and `Encoder::set_srgb` methods.
|
||||||
|
* Improved the compression settings API for encoding.
|
||||||
|
* `Decoder` now requires a reader that implements `Seek` and `BufRead` traits.
|
||||||
|
* Bump bitflags dependency to 2.0.
|
||||||
|
|
||||||
|
### Other additions
|
||||||
|
|
||||||
|
* Added `Reader::read_row` method.
|
||||||
|
* Add support for parsing eXIf chunk.
|
||||||
|
* Treat most auxiliary chunk errors as benign.
|
||||||
|
|
||||||
|
## 0.17.16
|
||||||
|
|
||||||
|
* Make gAMA and cHRM fallback optional for sRGB ([#547])
|
||||||
|
* Pass through nightly feature to crc32fast crate to get SIMD crc32 on Aarch64 ([#545])
|
||||||
|
* Fix bug in iCCP chunk encoding ([#458])
|
||||||
|
* Deprecate Info::encode ([#550])
|
||||||
|
|
||||||
|
[#545]: https://github.com/image-rs/image-png/pull/545
|
||||||
|
[#458]: https://github.com/image-rs/image-png/pull/548
|
||||||
|
[#550]: https://github.com/image-rs/image-png/pull/550
|
||||||
|
[#547]: https://github.com/image-rs/image-png/pull/547
|
||||||
|
|
||||||
## 0.17.15
|
## 0.17.15
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@ -7,7 +34,7 @@
|
|||||||
* Add support for parsing the sBIT chunk ([#524])
|
* Add support for parsing the sBIT chunk ([#524])
|
||||||
* Add support for parsing the bKGD chunk ([#538])
|
* Add support for parsing the bKGD chunk ([#538])
|
||||||
* Add support for parsing the cICP chunk ([#529])
|
* Add support for parsing the cICP chunk ([#529])
|
||||||
* Add support for parsing mDCv and cLLi chunks ([#528], ([#543]))
|
* Add support for parsing mDCV and cLLI chunks ([#528], ([#543]))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
966
third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/Cargo.lock
generated
vendored
Normal file
966
third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,966 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cast"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"ciborium-ll",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "3.2.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"clap_derive",
|
||||||
|
"clap_lex",
|
||||||
|
"indexmap",
|
||||||
|
"once_cell",
|
||||||
|
"strsim",
|
||||||
|
"termcolor",
|
||||||
|
"textwrap",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "3.2.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
|
||||||
|
dependencies = [
|
||||||
|
"anes",
|
||||||
|
"atty",
|
||||||
|
"cast",
|
||||||
|
"ciborium",
|
||||||
|
"clap",
|
||||||
|
"criterion-plot",
|
||||||
|
"itertools",
|
||||||
|
"lazy_static",
|
||||||
|
"num-traits",
|
||||||
|
"oorandom",
|
||||||
|
"plotters",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"tinytemplate",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion-plot"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
|
dependencies = [
|
||||||
|
"cast",
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"libz-rs-sys",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getopts"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "home"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.170"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libz-rs-sys"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "902bc563b5d65ad9bba616b490842ef0651066a1a1dc3ce1087113ffcb873c8d"
|
||||||
|
dependencies = [
|
||||||
|
"zlib-rs",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oorandom"
|
||||||
|
version = "11.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_str_bytes"
|
||||||
|
version = "6.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"plotters-backend",
|
||||||
|
"plotters-svg",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-backend"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-svg"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
|
||||||
|
dependencies = [
|
||||||
|
"plotters-backend",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.18.0-rc"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"byteorder",
|
||||||
|
"clap",
|
||||||
|
"crc32fast",
|
||||||
|
"criterion",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"getopts",
|
||||||
|
"glob",
|
||||||
|
"miniz_oxide",
|
||||||
|
"rand",
|
||||||
|
"term",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.218"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.218"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.139"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "term"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3bb6001afcea98122260987f8b7b5da969ecad46dbf0b5453702f776b491a41"
|
||||||
|
dependencies = [
|
||||||
|
"home",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytemplate"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zlib-rs"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b20717f0917c908dc63de2e44e97f1e6b126ca58d0e391cee86d504eb8fbd05"
|
@ -10,10 +10,10 @@
|
|||||||
# See Cargo.toml.orig for the original contents.
|
# See Cargo.toml.orig for the original contents.
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
rust-version = "1.57"
|
rust-version = "1.65"
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.16"
|
version = "0.18.0-rc"
|
||||||
authors = ["The image-rs Developers"]
|
authors = ["The image-rs Developers"]
|
||||||
build = false
|
build = false
|
||||||
include = [
|
include = [
|
||||||
@ -56,10 +56,6 @@ path = "examples/png-generate.rs"
|
|||||||
name = "pngcheck"
|
name = "pngcheck"
|
||||||
path = "examples/pngcheck.rs"
|
path = "examples/pngcheck.rs"
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "show"
|
|
||||||
path = "examples/show.rs"
|
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "decoder"
|
name = "decoder"
|
||||||
path = "benches/decoder.rs"
|
path = "benches/decoder.rs"
|
||||||
@ -78,7 +74,7 @@ harness = false
|
|||||||
required-features = ["benchmarks"]
|
required-features = ["benchmarks"]
|
||||||
|
|
||||||
[dependencies.bitflags]
|
[dependencies.bitflags]
|
||||||
version = "1.0"
|
version = "2.0"
|
||||||
|
|
||||||
[dependencies.crc32fast]
|
[dependencies.crc32fast]
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -87,7 +83,7 @@ version = "1.2.0"
|
|||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
|
||||||
[dependencies.flate2]
|
[dependencies.flate2]
|
||||||
version = "1.0.11"
|
version = "1.0.35"
|
||||||
|
|
||||||
[dependencies.miniz_oxide]
|
[dependencies.miniz_oxide]
|
||||||
version = "0.8"
|
version = "0.8"
|
||||||
@ -109,11 +105,6 @@ version = "0.4.0"
|
|||||||
[dev-dependencies.getopts]
|
[dev-dependencies.getopts]
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
|
||||||
[dev-dependencies.glium]
|
|
||||||
version = "0.32"
|
|
||||||
features = ["glutin"]
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dev-dependencies.glob]
|
[dev-dependencies.glob]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
|
|
||||||
@ -126,6 +117,7 @@ version = "1.0.1"
|
|||||||
[features]
|
[features]
|
||||||
benchmarks = []
|
benchmarks = []
|
||||||
unstable = ["crc32fast/nightly"]
|
unstable = ["crc32fast/nightly"]
|
||||||
|
zlib-rs = ["flate2/zlib-rs"]
|
||||||
|
|
||||||
[lints.rust.unexpected_cfgs]
|
[lints.rust.unexpected_cfgs]
|
||||||
level = "warn"
|
level = "warn"
|
18
third_party/rust/chromium_crates_io/vendor/png-0.17.16/Cargo.toml.orig → third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/Cargo.toml.orig
generated
vendored
18
third_party/rust/chromium_crates_io/vendor/png-0.17.16/Cargo.toml.orig → third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/Cargo.toml.orig
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.16"
|
version = "0.18.0-rc"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
description = "PNG decoding and encoding library in pure Rust"
|
description = "PNG decoding and encoding library in pure Rust"
|
||||||
@ -8,8 +8,8 @@ categories = ["multimedia::images"]
|
|||||||
authors = ["The image-rs Developers"]
|
authors = ["The image-rs Developers"]
|
||||||
repository = "https://github.com/image-rs/image-png"
|
repository = "https://github.com/image-rs/image-png"
|
||||||
|
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
rust-version = "1.57"
|
rust-version = "1.65"
|
||||||
include = [
|
include = [
|
||||||
"/LICENSE-MIT",
|
"/LICENSE-MIT",
|
||||||
"/LICENSE-APACHE",
|
"/LICENSE-APACHE",
|
||||||
@ -21,10 +21,10 @@ include = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
bitflags = "2.0"
|
||||||
crc32fast = "1.2.0"
|
crc32fast = "1.2.0"
|
||||||
fdeflate = "0.3.3"
|
fdeflate = "0.3.3"
|
||||||
flate2 = "1.0.11"
|
flate2 = "1.0.35"
|
||||||
miniz_oxide = { version = "0.8", features = ["simd"] }
|
miniz_oxide = { version = "0.8", features = ["simd"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@ -33,13 +33,19 @@ byteorder = "1.5.0"
|
|||||||
clap = { version = "3.0", features = ["derive"] }
|
clap = { version = "3.0", features = ["derive"] }
|
||||||
criterion = "0.4.0"
|
criterion = "0.4.0"
|
||||||
getopts = "0.2.14"
|
getopts = "0.2.14"
|
||||||
glium = { version = "0.32", features = ["glutin"], default-features = false }
|
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
term = "1.0.1"
|
term = "1.0.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
# Use nightly-only features for a minor performance boost in PNG decoding
|
||||||
unstable = ["crc32fast/nightly"]
|
unstable = ["crc32fast/nightly"]
|
||||||
|
# Use zlib-rs for faster PNG encoding at the cost of some `unsafe` code.
|
||||||
|
# WARNING: this changes the flate2 backend for your entire dependency tree!
|
||||||
|
# While the `png` crate always uses fully memory-safe decoding,
|
||||||
|
# this enables zlib-rs and introduces some unsafe code to all other crates
|
||||||
|
# that rely on flate2, including the decoding codepaths.
|
||||||
|
zlib-rs = ["flate2/zlib-rs"]
|
||||||
benchmarks = []
|
benchmarks = []
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
@ -1,4 +1,4 @@
|
|||||||
use std::fs;
|
use std::{fs, io::Cursor};
|
||||||
|
|
||||||
use criterion::{
|
use criterion::{
|
||||||
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, Throughput,
|
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, Throughput,
|
||||||
@ -41,6 +41,13 @@ fn load_all(c: &mut Criterion) {
|
|||||||
bench_noncompressed_png(&mut g, 2048, 0x7fffffff); // 16 MB
|
bench_noncompressed_png(&mut g, 2048, 0x7fffffff); // 16 MB
|
||||||
bench_noncompressed_png(&mut g, 12288, 0x7fffffff); // 576 MB
|
bench_noncompressed_png(&mut g, 12288, 0x7fffffff); // 576 MB
|
||||||
g.finish();
|
g.finish();
|
||||||
|
|
||||||
|
// Incremental decoding via `read_row`
|
||||||
|
let mut g = c.benchmark_group("row-by-row");
|
||||||
|
let mut data = Vec::new();
|
||||||
|
test_utils::write_noncompressed_png(&mut data, 128, 4096);
|
||||||
|
bench_read_row(&mut g, data, "128x128-4k-idat");
|
||||||
|
g.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group! {benches, load_all}
|
criterion_group! {benches, load_all}
|
||||||
@ -52,21 +59,12 @@ fn bench_noncompressed_png(g: &mut BenchmarkGroup<WallTime>, size: u32, idat_byt
|
|||||||
bench_file(g, data, format!("{size}x{size}.png"));
|
bench_file(g, data, format!("{size}x{size}.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This benchmarks decoding via a call to `Reader::next_frame`.
|
||||||
fn bench_file(g: &mut BenchmarkGroup<WallTime>, data: Vec<u8>, name: String) {
|
fn bench_file(g: &mut BenchmarkGroup<WallTime>, data: Vec<u8>, name: String) {
|
||||||
if data.len() > 1_000_000 {
|
if data.len() > 1_000_000 {
|
||||||
g.sample_size(10);
|
g.sample_size(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_reader(data: &[u8]) -> Reader<&[u8]> {
|
|
||||||
let mut decoder = Decoder::new(data);
|
|
||||||
|
|
||||||
// Cover default transformations used by the `image` crate when constructing
|
|
||||||
// `image::codecs::png::PngDecoder`.
|
|
||||||
decoder.set_transformations(Transformations::EXPAND);
|
|
||||||
|
|
||||||
decoder.read_info().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut reader = create_reader(data.as_slice());
|
let mut reader = create_reader(data.as_slice());
|
||||||
let mut image = vec![0; reader.output_buffer_size()];
|
let mut image = vec![0; reader.output_buffer_size()];
|
||||||
let info = reader.next_frame(&mut image).unwrap();
|
let info = reader.next_frame(&mut image).unwrap();
|
||||||
@ -79,3 +77,30 @@ fn bench_file(g: &mut BenchmarkGroup<WallTime>, data: Vec<u8>, name: String) {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This benchmarks decoding via a sequence of `Reader::read_row` calls.
|
||||||
|
fn bench_read_row(g: &mut BenchmarkGroup<WallTime>, data: Vec<u8>, name: &str) {
|
||||||
|
let reader = create_reader(data.as_slice());
|
||||||
|
let mut image = vec![0; reader.output_buffer_size()];
|
||||||
|
let bytes_per_row = reader.output_line_size(reader.info().width);
|
||||||
|
g.throughput(Throughput::Bytes(image.len() as u64));
|
||||||
|
g.bench_with_input(name, &data, |b, data| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut reader = create_reader(data.as_slice());
|
||||||
|
|
||||||
|
for output_row in image.chunks_exact_mut(bytes_per_row) {
|
||||||
|
reader.read_row(output_row).unwrap().unwrap();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_reader(data: &[u8]) -> Reader<Cursor<&[u8]>> {
|
||||||
|
let mut decoder = Decoder::new(Cursor::new(data));
|
||||||
|
|
||||||
|
// Cover default transformations used by the `image` crate when constructing
|
||||||
|
// `image::codecs::png::PngDecoder`.
|
||||||
|
decoder.set_transformations(Transformations::EXPAND);
|
||||||
|
|
||||||
|
decoder.read_info().unwrap()
|
||||||
|
}
|
@ -9,17 +9,12 @@
|
|||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
||||||
use png::benchable_apis::unfilter;
|
use png::benchable_apis::unfilter;
|
||||||
use png::FilterType;
|
use png::Filter;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
fn unfilter_all(c: &mut Criterion) {
|
fn unfilter_all(c: &mut Criterion) {
|
||||||
let bpps = [1, 2, 3, 4, 6, 8];
|
let bpps = [1, 2, 3, 4, 6, 8];
|
||||||
let filters = [
|
let filters = [Filter::Sub, Filter::Up, Filter::Avg, Filter::Paeth];
|
||||||
FilterType::Sub,
|
|
||||||
FilterType::Up,
|
|
||||||
FilterType::Avg,
|
|
||||||
FilterType::Paeth,
|
|
||||||
];
|
|
||||||
for &filter in filters.iter() {
|
for &filter in filters.iter() {
|
||||||
for &bpp in bpps.iter() {
|
for &bpp in bpps.iter() {
|
||||||
bench_unfilter(c, filter, bpp);
|
bench_unfilter(c, filter, bpp);
|
||||||
@ -30,7 +25,7 @@ fn unfilter_all(c: &mut Criterion) {
|
|||||||
criterion_group!(benches, unfilter_all);
|
criterion_group!(benches, unfilter_all);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
fn bench_unfilter(c: &mut Criterion, filter: FilterType, bpp: u8) {
|
fn bench_unfilter(c: &mut Criterion, filter: Filter, bpp: u8) {
|
||||||
let mut group = c.benchmark_group("unfilter");
|
let mut group = c.benchmark_group("unfilter");
|
||||||
|
|
||||||
fn get_random_bytes<R: Rng>(rng: &mut R, n: usize) -> Vec<u8> {
|
fn get_random_bytes<R: Rng>(rng: &mut R, n: usize) -> Vec<u8> {
|
@ -1,7 +1,7 @@
|
|||||||
/// Tests "editing"/re-encoding of an image:
|
/// Tests "editing"/re-encoding of an image:
|
||||||
/// decoding, editing, re-encoding
|
/// decoding, editing, re-encoding
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufWriter;
|
use std::io::{BufReader, BufWriter};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
pub type BoxResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
pub type BoxResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ fn main() -> BoxResult<()> {
|
|||||||
let path_in = Path::new(r"./tests/pngsuite/basi0g01.png");
|
let path_in = Path::new(r"./tests/pngsuite/basi0g01.png");
|
||||||
// The decoder is a build for reader and can be used to set various decoding options
|
// The decoder is a build for reader and can be used to set various decoding options
|
||||||
// via `Transformations`. The default output transformation is `Transformations::IDENTITY`.
|
// via `Transformations`. The default output transformation is `Transformations::IDENTITY`.
|
||||||
let decoder = png::Decoder::new(File::open(path_in)?);
|
let decoder = png::Decoder::new(BufReader::new(File::open(path_in)?));
|
||||||
let mut reader = decoder.read_info()?;
|
let mut reader = decoder.read_info()?;
|
||||||
// Allocate the output buffer.
|
// Allocate the output buffer.
|
||||||
let png_info = reader.info();
|
let png_info = reader.info();
|
@ -1,4 +1,4 @@
|
|||||||
use std::{fs, path::PathBuf};
|
use std::{fs, io::Cursor, path::PathBuf};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use png::Decoder;
|
use png::Decoder;
|
||||||
@ -43,20 +43,16 @@ fn run_encode(
|
|||||||
encoder.set_depth(bit_depth);
|
encoder.set_depth(bit_depth);
|
||||||
encoder.set_compression(match args.speed {
|
encoder.set_compression(match args.speed {
|
||||||
Speed::Fast => png::Compression::Fast,
|
Speed::Fast => png::Compression::Fast,
|
||||||
Speed::Default => png::Compression::Default,
|
Speed::Default => png::Compression::Balanced,
|
||||||
Speed::Best => png::Compression::Best,
|
Speed::Best => png::Compression::High,
|
||||||
});
|
});
|
||||||
encoder.set_filter(match args.filter {
|
encoder.set_filter(match args.filter {
|
||||||
Filter::None => png::FilterType::NoFilter,
|
Filter::None => png::Filter::NoFilter,
|
||||||
Filter::Sub => png::FilterType::Sub,
|
Filter::Sub => png::Filter::Sub,
|
||||||
Filter::Up => png::FilterType::Up,
|
Filter::Up => png::Filter::Up,
|
||||||
Filter::Average => png::FilterType::Avg,
|
Filter::Average => png::Filter::Avg,
|
||||||
Filter::Paeth => png::FilterType::Paeth,
|
Filter::Paeth => png::Filter::Paeth,
|
||||||
Filter::Adaptive => png::FilterType::Paeth,
|
Filter::Adaptive => png::Filter::Adaptive,
|
||||||
});
|
|
||||||
encoder.set_adaptive_filter(match args.filter {
|
|
||||||
Filter::Adaptive => png::AdaptiveFilterType::Adaptive,
|
|
||||||
_ => png::AdaptiveFilterType::NonAdaptive,
|
|
||||||
});
|
});
|
||||||
let mut encoder = encoder.write_header().unwrap();
|
let mut encoder = encoder.write_header().unwrap();
|
||||||
encoder.write_image_data(image).unwrap();
|
encoder.write_image_data(image).unwrap();
|
||||||
@ -66,7 +62,7 @@ fn run_encode(
|
|||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn run_decode(image: &[u8], output: &mut [u8]) {
|
fn run_decode(image: &[u8], output: &mut [u8]) {
|
||||||
let mut reader = Decoder::new(image).read_info().unwrap();
|
let mut reader = Decoder::new(Cursor::new(image)).read_info().unwrap();
|
||||||
reader.next_frame(output).unwrap();
|
reader.next_frame(output).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +107,7 @@ fn main() {
|
|||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
let data = fs::read(entry.path()).unwrap();
|
let data = fs::read(entry.path()).unwrap();
|
||||||
let mut decoder = Decoder::new(&*data);
|
let mut decoder = Decoder::new(Cursor::new(&*data));
|
||||||
if decoder.read_header_info().ok().map(|h| h.color_type)
|
if decoder.read_header_info().ok().map(|h| h.color_type)
|
||||||
== Some(png::ColorType::Indexed)
|
== Some(png::ColorType::Indexed)
|
||||||
{
|
{
|
@ -2,12 +2,13 @@
|
|||||||
//! This module is gated behind the "benchmarks" feature.
|
//! This module is gated behind the "benchmarks" feature.
|
||||||
|
|
||||||
use crate::common::BytesPerPixel;
|
use crate::common::BytesPerPixel;
|
||||||
use crate::filter::FilterType;
|
use crate::filter::{Filter, RowFilter};
|
||||||
use crate::{BitDepth, ColorType, Info};
|
use crate::{BitDepth, ColorType, Info};
|
||||||
|
|
||||||
/// Re-exporting `unfilter` to make it easier to benchmark, despite some items being only
|
/// Re-exporting `unfilter` to make it easier to benchmark, despite some items being only
|
||||||
/// `pub(crate)`: `fn unfilter`, `enum BytesPerPixel`.
|
/// `pub(crate)`: `fn unfilter`, `enum BytesPerPixel`.
|
||||||
pub fn unfilter(filter: FilterType, tbpp: u8, previous: &[u8], current: &mut [u8]) {
|
pub fn unfilter(filter: Filter, tbpp: u8, previous: &[u8], current: &mut [u8]) {
|
||||||
|
let filter = RowFilter::from_method(filter).unwrap(); // RowFilter type is private
|
||||||
let tbpp = BytesPerPixel::from_usize(tbpp as usize);
|
let tbpp = BytesPerPixel::from_usize(tbpp as usize);
|
||||||
crate::filter::unfilter(filter, tbpp, previous, current)
|
crate::filter::unfilter(filter, tbpp, previous, current)
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
//! Common types shared between the encoder and decoder
|
//! Common types shared between the encoder and decoder
|
||||||
use crate::text_metadata::{EncodableTextChunk, ITXtChunk, TEXtChunk, ZTXtChunk};
|
use crate::text_metadata::{ITXtChunk, TEXtChunk, ZTXtChunk};
|
||||||
|
#[allow(unused_imports)] // used by doc comments only
|
||||||
|
use crate::Filter;
|
||||||
use crate::{chunk, encoder};
|
use crate::{chunk, encoder};
|
||||||
use io::Write;
|
use io::Write;
|
||||||
use std::{borrow::Cow, convert::TryFrom, fmt, io};
|
use std::{borrow::Cow, convert::TryFrom, fmt, io};
|
||||||
@ -77,6 +79,16 @@ impl ColorType {
|
|||||||
|| self == ColorType::Rgba))
|
|| self == ColorType::Rgba))
|
||||||
|| (bit_depth == BitDepth::Sixteen && self == ColorType::Indexed)
|
|| (bit_depth == BitDepth::Sixteen && self == ColorType::Indexed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn bits_per_pixel(&self, bit_depth: BitDepth) -> usize {
|
||||||
|
self.samples() * bit_depth as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn bytes_per_pixel(&self, bit_depth: BitDepth) -> usize {
|
||||||
|
// If adjusting this for expansion or other transformation passes, remember to keep the old
|
||||||
|
// implementation for bpp_in_prediction, which is internal to the png specification.
|
||||||
|
self.samples() * ((bit_depth as usize + 7) >> 3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bit depth of the PNG file.
|
/// Bit depth of the PNG file.
|
||||||
@ -303,33 +315,104 @@ impl AnimationControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The type and strength of applied compression.
|
/// The type and strength of applied compression.
|
||||||
|
///
|
||||||
|
/// This is a simple, high-level interface that will automatically choose
|
||||||
|
/// the appropriate DEFLATE compression mode and PNG filter.
|
||||||
|
///
|
||||||
|
/// If you need more control over the encoding parameters,
|
||||||
|
/// you can set the [DeflateCompression] and [Filter] manually.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum Compression {
|
pub enum Compression {
|
||||||
/// Default level
|
/// No compression whatsoever. Fastest, but results in large files.
|
||||||
Default,
|
NoCompression,
|
||||||
/// Fast minimal compression
|
/// Extremely fast but light compression.
|
||||||
Fast,
|
Fastest,
|
||||||
/// Higher compression level
|
/// Extremely fast compression with a decent compression ratio.
|
||||||
///
|
///
|
||||||
/// Best in this context isn't actually the highest possible level
|
/// Significantly outperforms libpng and other popular encoders
|
||||||
/// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
|
/// by using a [specialized DEFLATE implementation tuned for PNG](https://crates.io/crates/fdeflate),
|
||||||
/// library.
|
/// while still providing better compression ratio than the fastest modes of other encoders.
|
||||||
Best,
|
Fast,
|
||||||
#[deprecated(
|
/// Balances encoding speed and compression ratio
|
||||||
since = "0.17.6",
|
Balanced,
|
||||||
note = "use one of the other compression levels instead, such as 'fast'"
|
/// Spend more time to produce a slightly smaller file than with `Default`
|
||||||
)]
|
High,
|
||||||
Huffman,
|
|
||||||
#[deprecated(
|
|
||||||
since = "0.17.6",
|
|
||||||
note = "use one of the other compression levels instead, such as 'fast'"
|
|
||||||
)]
|
|
||||||
Rle,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Compression {
|
impl Default for Compression {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Default
|
Self::Balanced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Advanced compression settings with more customization options than [Compression].
|
||||||
|
///
|
||||||
|
/// Note that this setting only affects DEFLATE compression.
|
||||||
|
/// Another setting that influences the compression ratio and lets you choose
|
||||||
|
/// between encoding speed and compression ratio is the [Filter].
|
||||||
|
///
|
||||||
|
/// ### Stability guarantees
|
||||||
|
///
|
||||||
|
/// The implementation details of DEFLATE compression may evolve over time,
|
||||||
|
/// even without a semver-breaking change to the version of `png` crate.
|
||||||
|
///
|
||||||
|
/// If a certain compression setting is superseded by other options,
|
||||||
|
/// it may be marked deprecated and remapped to a different option.
|
||||||
|
/// You will see a deprecation notice when compiling code relying on such options.
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum DeflateCompression {
|
||||||
|
/// Do not compress the data at all.
|
||||||
|
///
|
||||||
|
/// Useful for incompressible images,
|
||||||
|
/// or when speed is paramount and you don't care about size at all.
|
||||||
|
///
|
||||||
|
/// This mode also disables filters, forcing [Filter::NoFilter].
|
||||||
|
NoCompression,
|
||||||
|
|
||||||
|
/// Excellent for creating lightly compressed PNG images very quickly.
|
||||||
|
///
|
||||||
|
/// Uses the [fdeflate](https://crates.io/crates/fdeflate) crate under the hood
|
||||||
|
/// to achieve speeds far exceeding what libpng is capable of
|
||||||
|
/// while still providing a decent compression ratio.
|
||||||
|
FdeflateUltraFast,
|
||||||
|
|
||||||
|
/// Compression level between 1 and 9, where higher values mean better compression at the cost of
|
||||||
|
/// speed.
|
||||||
|
///
|
||||||
|
/// This is currently implemented via [flate2](https://crates.io/crates/flate2) crate
|
||||||
|
/// by passing through the [compression level](flate2::Compression::new).
|
||||||
|
///
|
||||||
|
/// The implementation details and the exact meaning of each level may change in the future,
|
||||||
|
/// including in semver-compatible releases.
|
||||||
|
Level(u8),
|
||||||
|
// Other variants can be added in the future
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DeflateCompression {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::from_simple(Compression::Balanced)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeflateCompression {
|
||||||
|
pub(crate) fn from_simple(value: Compression) -> Self {
|
||||||
|
match value {
|
||||||
|
Compression::NoCompression => Self::NoCompression,
|
||||||
|
Compression::Fastest => Self::FdeflateUltraFast,
|
||||||
|
Compression::Fast => Self::FdeflateUltraFast,
|
||||||
|
Compression::Balanced => Self::Level(flate2::Compression::default().level() as u8),
|
||||||
|
Compression::High => Self::Level(flate2::Compression::best().level() as u8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn closest_flate2_level(&self) -> flate2::Compression {
|
||||||
|
match self {
|
||||||
|
DeflateCompression::NoCompression => flate2::Compression::none(),
|
||||||
|
DeflateCompression::FdeflateUltraFast => flate2::Compression::new(1),
|
||||||
|
DeflateCompression::Level(level) => flate2::Compression::new(u32::from(*level)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +670,6 @@ pub struct Info<'a> {
|
|||||||
|
|
||||||
pub frame_control: Option<FrameControl>,
|
pub frame_control: Option<FrameControl>,
|
||||||
pub animation_control: Option<AnimationControl>,
|
pub animation_control: Option<AnimationControl>,
|
||||||
pub compression: Compression,
|
|
||||||
/// Gamma of the source system.
|
/// Gamma of the source system.
|
||||||
/// Set by both `gAMA` as well as to a replacement by `sRGB` chunk.
|
/// Set by both `gAMA` as well as to a replacement by `sRGB` chunk.
|
||||||
pub source_gamma: Option<ScaledFloat>,
|
pub source_gamma: Option<ScaledFloat>,
|
||||||
@ -633,9 +715,6 @@ impl Default for Info<'_> {
|
|||||||
pixel_dims: None,
|
pixel_dims: None,
|
||||||
frame_control: None,
|
frame_control: None,
|
||||||
animation_control: None,
|
animation_control: None,
|
||||||
// Default to `deflate::Compression::Fast` and `filter::FilterType::Sub`
|
|
||||||
// to maintain backward compatible output.
|
|
||||||
compression: Compression::Fast,
|
|
||||||
source_gamma: None,
|
source_gamma: None,
|
||||||
source_chromaticities: None,
|
source_chromaticities: None,
|
||||||
srgb: None,
|
srgb: None,
|
||||||
@ -683,14 +762,14 @@ impl Info<'_> {
|
|||||||
|
|
||||||
/// Returns the number of bits per pixel.
|
/// Returns the number of bits per pixel.
|
||||||
pub fn bits_per_pixel(&self) -> usize {
|
pub fn bits_per_pixel(&self) -> usize {
|
||||||
self.color_type.samples() * self.bit_depth as usize
|
self.color_type.bits_per_pixel(self.bit_depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of bytes per pixel.
|
/// Returns the number of bytes per pixel.
|
||||||
pub fn bytes_per_pixel(&self) -> usize {
|
pub fn bytes_per_pixel(&self) -> usize {
|
||||||
// If adjusting this for expansion or other transformation passes, remember to keep the old
|
// If adjusting this for expansion or other transformation passes, remember to keep the old
|
||||||
// implementation for bpp_in_prediction, which is internal to the png specification.
|
// implementation for bpp_in_prediction, which is internal to the png specification.
|
||||||
self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
|
self.color_type.bytes_per_pixel(self.bit_depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of bytes for this pixel used in prediction.
|
/// Return the number of bytes for this pixel used in prediction.
|
||||||
@ -725,6 +804,24 @@ impl Info<'_> {
|
|||||||
.raw_row_length_from_width(self.bit_depth, width)
|
.raw_row_length_from_width(self.bit_depth, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gamma dependent on sRGB chunk
|
||||||
|
pub fn gamma(&self) -> Option<ScaledFloat> {
|
||||||
|
if self.srgb.is_some() {
|
||||||
|
Some(crate::srgb::substitute_gamma())
|
||||||
|
} else {
|
||||||
|
self.gama_chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Chromaticities dependent on sRGB chunk
|
||||||
|
pub fn chromaticities(&self) -> Option<SourceChromaticities> {
|
||||||
|
if self.srgb.is_some() {
|
||||||
|
Some(crate::srgb::substitute_chromaticities())
|
||||||
|
} else {
|
||||||
|
self.chrm_chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Mark the image data as conforming to the SRGB color space with the specified rendering intent.
|
/// Mark the image data as conforming to the SRGB color space with the specified rendering intent.
|
||||||
///
|
///
|
||||||
/// Any ICC profiles will be ignored.
|
/// Any ICC profiles will be ignored.
|
||||||
@ -735,91 +832,6 @@ impl Info<'_> {
|
|||||||
self.srgb = Some(rendering_intent);
|
self.srgb = Some(rendering_intent);
|
||||||
self.icc_profile = None;
|
self.icc_profile = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode this header to the writer.
|
|
||||||
///
|
|
||||||
/// Note that this does _not_ include the PNG signature, it starts with the IHDR chunk and then
|
|
||||||
/// includes other chunks that were added to the header.
|
|
||||||
#[deprecated(note = "Use Encoder+Writer instead")]
|
|
||||||
pub fn encode<W: Write>(&self, mut w: W) -> encoder::Result<()> {
|
|
||||||
// Encode the IHDR chunk
|
|
||||||
let mut data = [0; 13];
|
|
||||||
data[..4].copy_from_slice(&self.width.to_be_bytes());
|
|
||||||
data[4..8].copy_from_slice(&self.height.to_be_bytes());
|
|
||||||
data[8] = self.bit_depth as u8;
|
|
||||||
data[9] = self.color_type as u8;
|
|
||||||
data[12] = self.interlaced as u8;
|
|
||||||
encoder::write_chunk(&mut w, chunk::IHDR, &data)?;
|
|
||||||
|
|
||||||
// Encode the pHYs chunk
|
|
||||||
if let Some(pd) = self.pixel_dims {
|
|
||||||
let mut phys_data = [0; 9];
|
|
||||||
phys_data[0..4].copy_from_slice(&pd.xppu.to_be_bytes());
|
|
||||||
phys_data[4..8].copy_from_slice(&pd.yppu.to_be_bytes());
|
|
||||||
match pd.unit {
|
|
||||||
Unit::Meter => phys_data[8] = 1,
|
|
||||||
Unit::Unspecified => phys_data[8] = 0,
|
|
||||||
}
|
|
||||||
encoder::write_chunk(&mut w, chunk::pHYs, &phys_data)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If specified, the sRGB information overrides the source gamma and chromaticities.
|
|
||||||
if let Some(srgb) = &self.srgb {
|
|
||||||
srgb.encode(&mut w)?;
|
|
||||||
|
|
||||||
// gAMA and cHRM are optional, for backwards compatibility
|
|
||||||
let srgb_gamma = crate::srgb::substitute_gamma();
|
|
||||||
if Some(srgb_gamma) == self.source_gamma {
|
|
||||||
srgb_gamma.encode_gama(&mut w)?
|
|
||||||
}
|
|
||||||
let srgb_chromaticities = crate::srgb::substitute_chromaticities();
|
|
||||||
if Some(srgb_chromaticities) == self.source_chromaticities {
|
|
||||||
srgb_chromaticities.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Some(gma) = self.source_gamma {
|
|
||||||
gma.encode_gama(&mut w)?
|
|
||||||
}
|
|
||||||
if let Some(chrms) = self.source_chromaticities {
|
|
||||||
chrms.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
if let Some(iccp) = &self.icc_profile {
|
|
||||||
encoder::write_iccp_chunk(&mut w, "_", iccp)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(exif) = &self.exif_metadata {
|
|
||||||
encoder::write_chunk(&mut w, chunk::eXIf, exif)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(actl) = self.animation_control {
|
|
||||||
actl.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The position of the PLTE chunk is important, it must come before the tRNS chunk and after
|
|
||||||
// many of the other metadata chunks.
|
|
||||||
if let Some(p) = &self.palette {
|
|
||||||
encoder::write_chunk(&mut w, chunk::PLTE, p)?;
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(t) = &self.trns {
|
|
||||||
encoder::write_chunk(&mut w, chunk::tRNS, t)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for text_chunk in &self.uncompressed_latin1_text {
|
|
||||||
text_chunk.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for text_chunk in &self.compressed_latin1_text {
|
|
||||||
text_chunk.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for text_chunk in &self.utf8_text {
|
|
||||||
text_chunk.encode(&mut w)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BytesPerPixel {
|
impl BytesPerPixel {
|
||||||
@ -876,6 +888,7 @@ bitflags::bitflags! {
|
|||||||
const SCALE_16 = 0x8000; // read only
|
const SCALE_16 = 0x8000; // read only
|
||||||
```
|
```
|
||||||
"]
|
"]
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct Transformations: u32 {
|
pub struct Transformations: u32 {
|
||||||
/// No transformation
|
/// No transformation
|
||||||
const IDENTITY = 0x00000; // read and write */
|
const IDENTITY = 0x00000; // read and write */
|
@ -10,7 +10,7 @@ use self::stream::{DecodeOptions, DecodingError, FormatErrorInner, CHUNK_BUFFER_
|
|||||||
use self::transform::{create_transform_fn, TransformFn};
|
use self::transform::{create_transform_fn, TransformFn};
|
||||||
use self::unfiltering_buffer::UnfilteringBuffer;
|
use self::unfiltering_buffer::UnfilteringBuffer;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::{BufRead, Seek};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::adam7::{self, Adam7Info};
|
use crate::adam7::{self, Adam7Info};
|
||||||
@ -86,7 +86,7 @@ impl Default for Limits {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// PNG Decoder
|
/// PNG Decoder
|
||||||
pub struct Decoder<R: Read> {
|
pub struct Decoder<R: BufRead + Seek> {
|
||||||
read_decoder: ReadDecoder<R>,
|
read_decoder: ReadDecoder<R>,
|
||||||
/// Output transformations
|
/// Output transformations
|
||||||
transform: Transformations,
|
transform: Transformations,
|
||||||
@ -121,7 +121,7 @@ impl<'data> Row<'data> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> Decoder<R> {
|
impl<R: BufRead + Seek> Decoder<R> {
|
||||||
/// Create a new decoder configuration with default limits.
|
/// Create a new decoder configuration with default limits.
|
||||||
pub fn new(r: R) -> Decoder<R> {
|
pub fn new(r: R) -> Decoder<R> {
|
||||||
Decoder::new_with_limits(r, Limits::default())
|
Decoder::new_with_limits(r, Limits::default())
|
||||||
@ -159,17 +159,18 @@ impl<R: Read> Decoder<R> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::fs::File;
|
/// use std::fs::File;
|
||||||
|
/// use std::io::BufReader;
|
||||||
/// use png::{Decoder, Limits};
|
/// use png::{Decoder, Limits};
|
||||||
/// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes.
|
/// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes.
|
||||||
/// let mut limits = Limits::default();
|
/// let mut limits = Limits::default();
|
||||||
/// limits.bytes = 3;
|
/// limits.bytes = 3;
|
||||||
/// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
|
/// let mut decoder = Decoder::new_with_limits(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()), limits);
|
||||||
/// assert!(decoder.read_info().is_err());
|
/// assert!(decoder.read_info().is_err());
|
||||||
///
|
///
|
||||||
/// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
|
/// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
|
||||||
/// let mut limits = Limits::default();
|
/// let mut limits = Limits::default();
|
||||||
/// limits.bytes = 10*1024;
|
/// limits.bytes = 10*1024;
|
||||||
/// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
|
/// let mut decoder = Decoder::new_with_limits(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()), limits);
|
||||||
/// assert!(decoder.read_info().is_ok());
|
/// assert!(decoder.read_info().is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_limits(&mut self, limits: Limits) {
|
pub fn set_limits(&mut self, limits: Limits) {
|
||||||
@ -248,8 +249,9 @@ impl<R: Read> Decoder<R> {
|
|||||||
/// eg.
|
/// eg.
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::fs::File;
|
/// use std::fs::File;
|
||||||
|
/// use std::io::BufReader;
|
||||||
/// use png::Decoder;
|
/// use png::Decoder;
|
||||||
/// let mut decoder = Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap());
|
/// let mut decoder = Decoder::new(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()));
|
||||||
/// decoder.set_ignore_text_chunk(true);
|
/// decoder.set_ignore_text_chunk(true);
|
||||||
/// assert!(decoder.read_info().is_ok());
|
/// assert!(decoder.read_info().is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
@ -262,8 +264,9 @@ impl<R: Read> Decoder<R> {
|
|||||||
/// eg.
|
/// eg.
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::fs::File;
|
/// use std::fs::File;
|
||||||
|
/// use std::io::BufReader;
|
||||||
/// use png::Decoder;
|
/// use png::Decoder;
|
||||||
/// let mut decoder = Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
|
/// let mut decoder = Decoder::new(BufReader::new(File::open("tests/iccp/broken_iccp.png").unwrap()));
|
||||||
/// decoder.set_ignore_iccp_chunk(true);
|
/// decoder.set_ignore_iccp_chunk(true);
|
||||||
/// assert!(decoder.read_info().is_ok());
|
/// assert!(decoder.read_info().is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
@ -281,7 +284,7 @@ impl<R: Read> Decoder<R> {
|
|||||||
/// PNG reader (mostly high-level interface)
|
/// PNG reader (mostly high-level interface)
|
||||||
///
|
///
|
||||||
/// Provides a high level that iterates over lines or whole images.
|
/// Provides a high level that iterates over lines or whole images.
|
||||||
pub struct Reader<R: Read> {
|
pub struct Reader<R: BufRead + Seek> {
|
||||||
decoder: ReadDecoder<R>,
|
decoder: ReadDecoder<R>,
|
||||||
bpp: BytesPerPixel,
|
bpp: BytesPerPixel,
|
||||||
subframe: SubframeInfo,
|
subframe: SubframeInfo,
|
||||||
@ -317,7 +320,7 @@ struct SubframeInfo {
|
|||||||
consumed_and_flushed: bool,
|
consumed_and_flushed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> Reader<R> {
|
impl<R: BufRead + Seek> Reader<R> {
|
||||||
/// Advances to the start of the next animation frame and
|
/// Advances to the start of the next animation frame and
|
||||||
/// returns a reference to the `FrameControl` info that describes it.
|
/// returns a reference to the `FrameControl` info that describes it.
|
||||||
/// Skips and discards the image data of the previous frame if necessary.
|
/// Skips and discards the image data of the previous frame if necessary.
|
||||||
@ -474,14 +477,45 @@ impl<R: Read> Reader<R> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the next processed row of the image
|
/// Returns the next processed row of the image (discarding `InterlaceInfo`).
|
||||||
|
///
|
||||||
|
/// See also [`Reader.read_row`], which reads into a caller-provided buffer.
|
||||||
pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
|
pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
|
||||||
self.next_interlaced_row()
|
self.next_interlaced_row()
|
||||||
.map(|v| v.map(|v| Row { data: v.data }))
|
.map(|v| v.map(|v| Row { data: v.data }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the next processed row of the image
|
/// Returns the next processed row of the image.
|
||||||
|
///
|
||||||
|
/// See also [`Reader.read_row`], which reads into a caller-provided buffer.
|
||||||
pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
|
pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
|
||||||
|
let mut output_buffer = mem::take(&mut self.scratch_buffer);
|
||||||
|
output_buffer.resize(self.output_line_size(self.info().width), 0u8);
|
||||||
|
let result = self.read_row(&mut output_buffer);
|
||||||
|
self.scratch_buffer = output_buffer;
|
||||||
|
result.map(move |option| {
|
||||||
|
option.map(move |interlace| {
|
||||||
|
let output_line_size = self.output_line_size_for_interlace_info(&interlace);
|
||||||
|
InterlacedRow {
|
||||||
|
data: &self.scratch_buffer[..output_line_size],
|
||||||
|
interlace,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads the next row of the image into the provided `output_buffer`.
|
||||||
|
/// `Ok(None)` will be returned if the current image frame has no more rows.
|
||||||
|
///
|
||||||
|
/// `output_buffer` needs to be long enough to accommodate [`Reader.output_line_size`] for
|
||||||
|
/// [`Info.width`] (initial interlaced rows may need less than that).
|
||||||
|
///
|
||||||
|
/// See also [`Reader.next_row`] and [`Reader.next_interlaced_row`], which read into a
|
||||||
|
/// `Reader`-owned buffer.
|
||||||
|
pub fn read_row(
|
||||||
|
&mut self,
|
||||||
|
output_buffer: &mut [u8],
|
||||||
|
) -> Result<Option<InterlaceInfo>, DecodingError> {
|
||||||
let interlace = match self.subframe.current_interlace_info.as_ref() {
|
let interlace = match self.subframe.current_interlace_info.as_ref() {
|
||||||
None => {
|
None => {
|
||||||
self.finish_decoding()?;
|
self.finish_decoding()?;
|
||||||
@ -498,24 +532,21 @@ impl<R: Read> Reader<R> {
|
|||||||
self.info().raw_row_length_from_width(width)
|
self.info().raw_row_length_from_width(width)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let output_line_size = self.output_line_size_for_interlace_info(&interlace);
|
||||||
|
let output_buffer = &mut output_buffer[..output_line_size];
|
||||||
|
|
||||||
|
self.next_interlaced_row_impl(rowlen, output_buffer)?;
|
||||||
|
|
||||||
|
Ok(Some(interlace))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_line_size_for_interlace_info(&self, interlace: &InterlaceInfo) -> usize {
|
||||||
let width = match interlace {
|
let width = match interlace {
|
||||||
InterlaceInfo::Adam7(Adam7Info { width, .. }) => width,
|
InterlaceInfo::Adam7(Adam7Info { width, .. }) => *width,
|
||||||
InterlaceInfo::Null(_) => self.subframe.width,
|
InterlaceInfo::Null(_) => self.subframe.width,
|
||||||
};
|
};
|
||||||
let output_line_size = self.output_line_size(width);
|
self.output_line_size(width)
|
||||||
|
|
||||||
// TODO: change the interface of `next_interlaced_row` to take an output buffer instead of
|
|
||||||
// making us return a reference to a buffer that we own.
|
|
||||||
let mut output_buffer = mem::take(&mut self.scratch_buffer);
|
|
||||||
output_buffer.resize(output_line_size, 0u8);
|
|
||||||
let ret = self.next_interlaced_row_impl(rowlen, &mut output_buffer);
|
|
||||||
self.scratch_buffer = output_buffer;
|
|
||||||
ret?;
|
|
||||||
|
|
||||||
Ok(Some(InterlacedRow {
|
|
||||||
data: &self.scratch_buffer[..output_line_size],
|
|
||||||
interlace,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the rest of the image and chunks and finish up, including text chunks or others
|
/// Read the rest of the image and chunks and finish up, including text chunks or others
|
@ -1,9 +1,7 @@
|
|||||||
use super::stream::{
|
use super::stream::{DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder};
|
||||||
DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder, CHUNK_BUFFER_SIZE,
|
|
||||||
};
|
|
||||||
use super::Limits;
|
use super::Limits;
|
||||||
|
|
||||||
use std::io::{BufRead, BufReader, ErrorKind, Read};
|
use std::io::{BufRead, ErrorKind, Read, Seek};
|
||||||
|
|
||||||
use crate::chunk;
|
use crate::chunk;
|
||||||
use crate::common::Info;
|
use crate::common::Info;
|
||||||
@ -18,14 +16,14 @@ use crate::common::Info;
|
|||||||
/// * `finish_decoding_image_data()` - discarding remaining data from `IDAT` / `fdAT` sequence
|
/// * `finish_decoding_image_data()` - discarding remaining data from `IDAT` / `fdAT` sequence
|
||||||
/// * `read_until_end_of_input()` - reading until `IEND` chunk
|
/// * `read_until_end_of_input()` - reading until `IEND` chunk
|
||||||
pub(crate) struct ReadDecoder<R: Read> {
|
pub(crate) struct ReadDecoder<R: Read> {
|
||||||
reader: BufReader<R>,
|
reader: R,
|
||||||
decoder: StreamingDecoder,
|
decoder: StreamingDecoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> ReadDecoder<R> {
|
impl<R: BufRead + Seek> ReadDecoder<R> {
|
||||||
pub fn new(r: R) -> Self {
|
pub fn new(r: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
|
reader: r,
|
||||||
decoder: StreamingDecoder::new(),
|
decoder: StreamingDecoder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,10 +32,7 @@ impl<R: Read> ReadDecoder<R> {
|
|||||||
let mut decoder = StreamingDecoder::new_with_options(options);
|
let mut decoder = StreamingDecoder::new_with_options(options);
|
||||||
decoder.limits = Limits::default();
|
decoder.limits = Limits::default();
|
||||||
|
|
||||||
Self {
|
Self { reader: r, decoder }
|
||||||
reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
|
|
||||||
decoder,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_limits(&mut self, limits: Limits) {
|
pub fn set_limits(&mut self, limits: Limits) {
|
@ -24,6 +24,7 @@ pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
|
|||||||
///
|
///
|
||||||
/// This is used only in fuzzing. `afl` automatically adds `--cfg fuzzing` to RUSTFLAGS which can
|
/// This is used only in fuzzing. `afl` automatically adds `--cfg fuzzing` to RUSTFLAGS which can
|
||||||
/// be used to detect that build.
|
/// be used to detect that build.
|
||||||
|
#[allow(unexpected_cfgs)]
|
||||||
const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
|
const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
|
||||||
|
|
||||||
/// Kind of `u32` value that is being read via `State::U32`.
|
/// Kind of `u32` value that is being read via `State::U32`.
|
||||||
@ -1141,74 +1142,69 @@ impl StreamingDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sbit(&mut self) -> Result<Decoded, DecodingError> {
|
fn parse_sbit(&mut self) -> Result<Decoded, DecodingError> {
|
||||||
let mut parse = || {
|
let info = self.info.as_mut().unwrap();
|
||||||
let info = self.info.as_mut().unwrap();
|
if info.palette.is_some() {
|
||||||
if info.palette.is_some() {
|
return Err(DecodingError::Format(
|
||||||
|
FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.have_idat {
|
||||||
|
return Err(DecodingError::Format(
|
||||||
|
FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.sbit.is_some() {
|
||||||
|
return Err(DecodingError::Format(
|
||||||
|
FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
|
||||||
|
// The sample depth for color type 3 is fixed at eight bits.
|
||||||
|
let sample_depth = if color_type == ColorType::Indexed {
|
||||||
|
BitDepth::Eight
|
||||||
|
} else {
|
||||||
|
bit_depth
|
||||||
|
};
|
||||||
|
self.limits
|
||||||
|
.reserve_bytes(self.current_chunk.raw_bytes.len())?;
|
||||||
|
let vec = self.current_chunk.raw_bytes.clone();
|
||||||
|
let len = vec.len();
|
||||||
|
|
||||||
|
// expected lenth of the chunk
|
||||||
|
let expected = match color_type {
|
||||||
|
ColorType::Grayscale => 1,
|
||||||
|
ColorType::Rgb | ColorType::Indexed => 3,
|
||||||
|
ColorType::GrayscaleAlpha => 2,
|
||||||
|
ColorType::Rgba => 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the sbit chunk size is valid.
|
||||||
|
if expected != len {
|
||||||
|
return Err(DecodingError::Format(
|
||||||
|
FormatErrorInner::InvalidSbitChunkSize {
|
||||||
|
color_type,
|
||||||
|
expected,
|
||||||
|
len,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
for sbit in &vec {
|
||||||
|
if *sbit < 1 || *sbit > sample_depth as u8 {
|
||||||
return Err(DecodingError::Format(
|
return Err(DecodingError::Format(
|
||||||
FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
|
FormatErrorInner::InvalidSbit {
|
||||||
));
|
sample_depth,
|
||||||
}
|
sbit: *sbit,
|
||||||
|
|
||||||
if self.have_idat {
|
|
||||||
return Err(DecodingError::Format(
|
|
||||||
FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.sbit.is_some() {
|
|
||||||
return Err(DecodingError::Format(
|
|
||||||
FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
|
|
||||||
// The sample depth for color type 3 is fixed at eight bits.
|
|
||||||
let sample_depth = if color_type == ColorType::Indexed {
|
|
||||||
BitDepth::Eight
|
|
||||||
} else {
|
|
||||||
bit_depth
|
|
||||||
};
|
|
||||||
self.limits
|
|
||||||
.reserve_bytes(self.current_chunk.raw_bytes.len())?;
|
|
||||||
let vec = self.current_chunk.raw_bytes.clone();
|
|
||||||
let len = vec.len();
|
|
||||||
|
|
||||||
// expected lenth of the chunk
|
|
||||||
let expected = match color_type {
|
|
||||||
ColorType::Grayscale => 1,
|
|
||||||
ColorType::Rgb | ColorType::Indexed => 3,
|
|
||||||
ColorType::GrayscaleAlpha => 2,
|
|
||||||
ColorType::Rgba => 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if the sbit chunk size is valid.
|
|
||||||
if expected != len {
|
|
||||||
return Err(DecodingError::Format(
|
|
||||||
FormatErrorInner::InvalidSbitChunkSize {
|
|
||||||
color_type,
|
|
||||||
expected,
|
|
||||||
len,
|
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for sbit in &vec {
|
info.sbit = Some(Cow::Owned(vec));
|
||||||
if *sbit < 1 || *sbit > sample_depth as u8 {
|
|
||||||
return Err(DecodingError::Format(
|
|
||||||
FormatErrorInner::InvalidSbit {
|
|
||||||
sample_depth,
|
|
||||||
sbit: *sbit,
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info.sbit = Some(Cow::Owned(vec));
|
|
||||||
Ok(Decoded::Nothing)
|
|
||||||
};
|
|
||||||
|
|
||||||
parse().ok();
|
|
||||||
Ok(Decoded::Nothing)
|
Ok(Decoded::Nothing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,11 +1341,6 @@ impl StreamingDecoder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
info.chrm_chunk = Some(source_chromaticities);
|
info.chrm_chunk = Some(source_chromaticities);
|
||||||
// Ignore chromaticities if sRGB profile is used.
|
|
||||||
if info.srgb.is_none() {
|
|
||||||
info.source_chromaticities = Some(source_chromaticities);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Decoded::Nothing)
|
Ok(Decoded::Nothing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1370,11 +1361,6 @@ impl StreamingDecoder {
|
|||||||
let source_gamma = ScaledFloat::from_scaled(source_gamma);
|
let source_gamma = ScaledFloat::from_scaled(source_gamma);
|
||||||
|
|
||||||
info.gama_chunk = Some(source_gamma);
|
info.gama_chunk = Some(source_gamma);
|
||||||
// Ignore chromaticities if sRGB profile is used.
|
|
||||||
if info.srgb.is_none() {
|
|
||||||
info.source_gamma = Some(source_gamma);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Decoded::Nothing)
|
Ok(Decoded::Nothing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1398,8 +1384,6 @@ impl StreamingDecoder {
|
|||||||
|
|
||||||
// Set srgb and override source gamma and chromaticities.
|
// Set srgb and override source gamma and chromaticities.
|
||||||
info.srgb = Some(rendering_intent);
|
info.srgb = Some(rendering_intent);
|
||||||
info.source_gamma = Some(crate::srgb::substitute_gamma());
|
|
||||||
info.source_chromaticities = Some(crate::srgb::substitute_chromaticities());
|
|
||||||
Ok(Decoded::Nothing)
|
Ok(Decoded::Nothing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1871,22 +1855,25 @@ mod tests {
|
|||||||
use super::ScaledFloat;
|
use super::ScaledFloat;
|
||||||
use super::SourceChromaticities;
|
use super::SourceChromaticities;
|
||||||
use crate::test_utils::*;
|
use crate::test_utils::*;
|
||||||
use crate::{Decoder, DecodingError, Reader};
|
use crate::{Decoder, DecodingError, Reader, SrgbRenderingIntent, Unit};
|
||||||
use approx::assert_relative_eq;
|
use approx::assert_relative_eq;
|
||||||
use byteorder::WriteBytesExt;
|
use byteorder::WriteBytesExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{ErrorKind, Read, Write};
|
use std::io::BufRead;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::io::Seek;
|
||||||
|
use std::io::{BufReader, ErrorKind, Read, Write};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn image_gamma() -> Result<(), ()> {
|
fn image_gamma() -> Result<(), ()> {
|
||||||
fn trial(path: &str, expected: Option<ScaledFloat>) {
|
fn trial(path: &str, expected: Option<ScaledFloat>) {
|
||||||
let decoder = crate::Decoder::new(File::open(path).unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let actual: Option<ScaledFloat> = reader.info().source_gamma;
|
let actual: Option<ScaledFloat> = reader.info().gamma();
|
||||||
assert!(actual == expected);
|
assert!(actual == expected);
|
||||||
}
|
}
|
||||||
trial("tests/pngsuite/f00n0g08.png", None);
|
trial("tests/pngsuite/f00n0g08.png", None);
|
||||||
@ -1925,9 +1912,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn image_source_chromaticities() -> Result<(), ()> {
|
fn image_source_chromaticities() -> Result<(), ()> {
|
||||||
fn trial(path: &str, expected: Option<SourceChromaticities>) {
|
fn trial(path: &str, expected: Option<SourceChromaticities>) {
|
||||||
let decoder = crate::Decoder::new(File::open(path).unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let actual: Option<SourceChromaticities> = reader.info().source_chromaticities;
|
let actual: Option<SourceChromaticities> = reader.info().chromaticities();
|
||||||
assert!(actual == expected);
|
assert!(actual == expected);
|
||||||
}
|
}
|
||||||
trial(
|
trial(
|
||||||
@ -2112,7 +2099,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn image_source_sbit() {
|
fn image_source_sbit() {
|
||||||
fn trial(path: &str, expected: Option<Cow<[u8]>>) {
|
fn trial(path: &str, expected: Option<Cow<[u8]>>) {
|
||||||
let decoder = crate::Decoder::new(File::open(path).unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
|
let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
|
||||||
assert!(actual == expected);
|
assert!(actual == expected);
|
||||||
@ -2139,7 +2126,9 @@ mod tests {
|
|||||||
// https://github.com/image-rs/image/issues/1825#issuecomment-1321798639,
|
// https://github.com/image-rs/image/issues/1825#issuecomment-1321798639,
|
||||||
// but the 2nd iCCP chunk has been altered manually (see the 2nd comment below for more
|
// but the 2nd iCCP chunk has been altered manually (see the 2nd comment below for more
|
||||||
// details).
|
// details).
|
||||||
let decoder = crate::Decoder::new(File::open("tests/bugfixes/issue#1825.png").unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(
|
||||||
|
File::open("tests/bugfixes/issue#1825.png").unwrap(),
|
||||||
|
));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
|
let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
|
||||||
|
|
||||||
@ -2162,24 +2151,67 @@ mod tests {
|
|||||||
enc.write_image_data(&[0]).unwrap();
|
enc.write_image_data(&[0]).unwrap();
|
||||||
enc.finish().unwrap();
|
enc.finish().unwrap();
|
||||||
|
|
||||||
let dec = crate::Decoder::new(encoded_image.as_slice());
|
let dec = crate::Decoder::new(Cursor::new(&encoded_image));
|
||||||
let dec = dec.read_info().unwrap();
|
let dec = dec.read_info().unwrap();
|
||||||
assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap());
|
assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_phys_roundtrip() {
|
||||||
|
let mut info = crate::Info::with_size(1, 1);
|
||||||
|
info.pixel_dims = Some(crate::PixelDimensions {
|
||||||
|
xppu: 12,
|
||||||
|
yppu: 34,
|
||||||
|
unit: Unit::Meter,
|
||||||
|
});
|
||||||
|
let mut encoded_image = Vec::new();
|
||||||
|
let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
|
||||||
|
let mut enc = enc.write_header().unwrap();
|
||||||
|
enc.write_image_data(&[0]).unwrap();
|
||||||
|
enc.finish().unwrap();
|
||||||
|
|
||||||
|
let dec = crate::Decoder::new(Cursor::new(&encoded_image));
|
||||||
|
let dec = dec.read_info().unwrap();
|
||||||
|
let phys = dec.info().pixel_dims.as_ref().unwrap();
|
||||||
|
assert_eq!(phys.xppu, 12);
|
||||||
|
assert_eq!(phys.yppu, 34);
|
||||||
|
assert_eq!(phys.unit, Unit::Meter);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_srgb_roundtrip() {
|
||||||
|
let mut info = crate::Info::with_size(1, 1);
|
||||||
|
info.srgb = Some(SrgbRenderingIntent::Saturation);
|
||||||
|
let mut encoded_image = Vec::new();
|
||||||
|
let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
|
||||||
|
let mut enc = enc.write_header().unwrap();
|
||||||
|
enc.write_image_data(&[0]).unwrap();
|
||||||
|
enc.finish().unwrap();
|
||||||
|
|
||||||
|
let dec = crate::Decoder::new(Cursor::new(&encoded_image));
|
||||||
|
let dec = dec.read_info().unwrap();
|
||||||
|
assert_eq!(dec.info().srgb.unwrap(), SrgbRenderingIntent::Saturation);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_png_with_broken_iccp() {
|
fn test_png_with_broken_iccp() {
|
||||||
let decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(
|
||||||
|
File::open("tests/iccp/broken_iccp.png").unwrap(),
|
||||||
|
));
|
||||||
assert!(decoder.read_info().is_ok());
|
assert!(decoder.read_info().is_ok());
|
||||||
let mut decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
|
let mut decoder = crate::Decoder::new(BufReader::new(
|
||||||
|
File::open("tests/iccp/broken_iccp.png").unwrap(),
|
||||||
|
));
|
||||||
decoder.set_ignore_iccp_chunk(true);
|
decoder.set_ignore_iccp_chunk(true);
|
||||||
assert!(decoder.read_info().is_ok());
|
assert!(decoder.read_info().is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test handling of `mDCV` and `cLLI` chunks.
|
/// Test handling of `cICP`, `mDCV`, and `cLLI` chunks.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mdcv_and_clli_chunks() {
|
fn test_cicp_mdcv_and_clli_chunks() {
|
||||||
let decoder = crate::Decoder::new(File::open("tests/bugfixes/cicp_pq.png").unwrap());
|
let decoder = crate::Decoder::new(BufReader::new(
|
||||||
|
File::open("tests/bugfixes/cicp_pq.png").unwrap(),
|
||||||
|
));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let info = reader.info();
|
let info = reader.info();
|
||||||
|
|
||||||
@ -2209,8 +2241,9 @@ mod tests {
|
|||||||
/// Test handling of `eXIf` chunk.
|
/// Test handling of `eXIf` chunk.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exif_chunk() {
|
fn test_exif_chunk() {
|
||||||
let decoder =
|
let decoder = crate::Decoder::new(BufReader::new(
|
||||||
crate::Decoder::new(File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap());
|
File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap(),
|
||||||
|
));
|
||||||
let reader = decoder.read_info().unwrap();
|
let reader = decoder.read_info().unwrap();
|
||||||
let info = reader.info();
|
let info = reader.info();
|
||||||
let exif = info.exif_metadata.as_ref().unwrap().as_ref();
|
let exif = info.exif_metadata.as_ref().unwrap().as_ref();
|
||||||
@ -2222,7 +2255,7 @@ mod tests {
|
|||||||
fn test_finishing_twice() {
|
fn test_finishing_twice() {
|
||||||
let mut png = Vec::new();
|
let mut png = Vec::new();
|
||||||
write_noncompressed_png(&mut png, 16, 1024);
|
write_noncompressed_png(&mut png, 16, 1024);
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
|
|
||||||
// First call to `finish` - expecting success.
|
// First call to `finish` - expecting success.
|
||||||
@ -2310,7 +2343,7 @@ mod tests {
|
|||||||
write_fdat_prefix(&mut png, 2, 8);
|
write_fdat_prefix(&mut png, 2, 8);
|
||||||
write_chunk(&mut png, b"fdAT", &[]);
|
write_chunk(&mut png, b"fdAT", &[]);
|
||||||
|
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
reader.next_frame(&mut buf).unwrap();
|
reader.next_frame(&mut buf).unwrap();
|
||||||
@ -2338,7 +2371,7 @@ mod tests {
|
|||||||
write_fdat_prefix(&mut png, 2, 8);
|
write_fdat_prefix(&mut png, 2, 8);
|
||||||
write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
|
write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
|
||||||
|
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
reader.next_frame(&mut buf).unwrap();
|
reader.next_frame(&mut buf).unwrap();
|
||||||
@ -2376,7 +2409,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Start decoding.
|
// Start decoding.
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
let Some(animation_control) = reader.info().animation_control else {
|
let Some(animation_control) = reader.info().animation_control else {
|
||||||
@ -2439,7 +2472,7 @@ mod tests {
|
|||||||
write_iend(&mut png);
|
write_iend(&mut png);
|
||||||
png
|
png
|
||||||
};
|
};
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
|
|
||||||
@ -2457,7 +2490,7 @@ mod tests {
|
|||||||
write_chunk(&mut png, b"IDAT", &[]);
|
write_chunk(&mut png, b"IDAT", &[]);
|
||||||
png
|
png
|
||||||
};
|
};
|
||||||
let decoder = Decoder::new(png.as_slice());
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
let Err(err) = decoder.read_info() else {
|
let Err(err) = decoder.read_info() else {
|
||||||
panic!("Expected an error")
|
panic!("Expected an error")
|
||||||
};
|
};
|
||||||
@ -2476,21 +2509,25 @@ mod tests {
|
|||||||
/// `StreamingInput` can be used by tests to simulate a streaming input
|
/// `StreamingInput` can be used by tests to simulate a streaming input
|
||||||
/// (e.g. a slow http response, where all bytes are not immediately available).
|
/// (e.g. a slow http response, where all bytes are not immediately available).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct StreamingInput(Rc<RefCell<StreamingInputState>>);
|
struct StreamingInput {
|
||||||
|
full_input: Vec<u8>,
|
||||||
|
state: Rc<RefCell<StreamingInputState>>,
|
||||||
|
}
|
||||||
|
|
||||||
struct StreamingInputState {
|
struct StreamingInputState {
|
||||||
full_input: Vec<u8>,
|
|
||||||
current_pos: usize,
|
current_pos: usize,
|
||||||
available_len: usize,
|
available_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StreamingInput {
|
impl StreamingInput {
|
||||||
fn new(full_input: Vec<u8>) -> Self {
|
fn new(full_input: Vec<u8>) -> Self {
|
||||||
Self(Rc::new(RefCell::new(StreamingInputState {
|
Self {
|
||||||
full_input,
|
full_input,
|
||||||
current_pos: 0,
|
state: Rc::new(RefCell::new(StreamingInputState {
|
||||||
available_len: 0,
|
current_pos: 0,
|
||||||
})))
|
available_len: 0,
|
||||||
|
})),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
|
fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
|
||||||
@ -2500,14 +2537,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expose_next_byte(&self) {
|
fn expose_next_byte(&self) {
|
||||||
let mut state = self.0.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
assert!(state.available_len < state.full_input.len());
|
assert!(state.available_len < self.full_input.len());
|
||||||
state.available_len += 1;
|
state.available_len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
|
fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
|
||||||
loop {
|
loop {
|
||||||
self.0.borrow_mut().current_pos = 0;
|
self.state.borrow_mut().current_pos = 0;
|
||||||
match Decoder::new(self.clone()).read_info() {
|
match Decoder::new(self.clone()).read_info() {
|
||||||
Ok(reader) => {
|
Ok(reader) => {
|
||||||
break reader;
|
break reader;
|
||||||
@ -2522,24 +2559,49 @@ mod tests {
|
|||||||
|
|
||||||
fn decode_full_input<F, R>(&self, f: F) -> R
|
fn decode_full_input<F, R>(&self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(Reader<&[u8]>) -> R,
|
F: FnOnce(Reader<Cursor<&[u8]>>) -> R,
|
||||||
{
|
{
|
||||||
let state = self.0.borrow();
|
let decoder = Decoder::new(Cursor::new(&*self.full_input));
|
||||||
let decoder = Decoder::new(state.full_input.as_slice());
|
|
||||||
f(decoder.read_info().unwrap())
|
f(decoder.read_info().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for StreamingInput {
|
impl Read for StreamingInput {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
let mut state = self.0.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
let mut available_bytes = &state.full_input[state.current_pos..state.available_len];
|
let mut available_bytes = &self.full_input[state.current_pos..state.available_len];
|
||||||
let number_of_read_bytes = available_bytes.read(buf)?;
|
let number_of_read_bytes = available_bytes.read(buf)?;
|
||||||
state.current_pos += number_of_read_bytes;
|
state.current_pos += number_of_read_bytes;
|
||||||
assert!(state.current_pos <= state.available_len);
|
assert!(state.current_pos <= state.available_len);
|
||||||
Ok(number_of_read_bytes)
|
Ok(number_of_read_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl BufRead for StreamingInput {
|
||||||
|
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
|
||||||
|
let state = self.state.borrow();
|
||||||
|
Ok(&self.full_input[state.current_pos..state.available_len])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume(&mut self, amt: usize) {
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
state.current_pos += amt;
|
||||||
|
assert!(state.current_pos <= state.available_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Seek for StreamingInput {
|
||||||
|
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
state.current_pos = match pos {
|
||||||
|
std::io::SeekFrom::Start(n) => n as usize,
|
||||||
|
std::io::SeekFrom::End(n) => (self.full_input.len() as i64 + n) as usize,
|
||||||
|
std::io::SeekFrom::Current(n) => (state.current_pos as i64 + n) as usize,
|
||||||
|
} as usize;
|
||||||
|
Ok(state.current_pos as u64)
|
||||||
|
}
|
||||||
|
fn stream_position(&mut self) -> std::io::Result<u64> {
|
||||||
|
Ok(self.state.borrow().current_pos as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Test resuming/retrying `Reader.next_frame` after `UnexpectedEof`.
|
/// Test resuming/retrying `Reader.next_frame` after `UnexpectedEof`.
|
||||||
#[test]
|
#[test]
|
||||||
@ -2645,25 +2707,25 @@ mod tests {
|
|||||||
|
|
||||||
/// Creates a ready-to-test [`Reader`] which decodes a PNG that contains:
|
/// Creates a ready-to-test [`Reader`] which decodes a PNG that contains:
|
||||||
/// IHDR, IDAT, IEND.
|
/// IHDR, IDAT, IEND.
|
||||||
fn create_reader_of_ihdr_idat() -> Reader<VecDeque<u8>> {
|
fn create_reader_of_ihdr_idat() -> Reader<Cursor<Vec<u8>>> {
|
||||||
let mut png = VecDeque::new();
|
let mut png = Vec::new();
|
||||||
write_noncompressed_png(&mut png, /* width = */ 16, /* idat_size = */ 1024);
|
write_noncompressed_png(&mut png, /* width = */ 16, /* idat_size = */ 1024);
|
||||||
Decoder::new(png).read_info().unwrap()
|
Decoder::new(Cursor::new(png)).read_info().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains:
|
/// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains:
|
||||||
/// IHDR, acTL, fcTL, IDAT, fcTL, fdAT, IEND. (i.e. IDAT is part of the animation)
|
/// IHDR, acTL, fcTL, IDAT, fcTL, fdAT, IEND. (i.e. IDAT is part of the animation)
|
||||||
fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<VecDeque<u8>> {
|
fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
|
||||||
let idat_width = 16;
|
let width = 16;
|
||||||
let mut fctl = crate::FrameControl {
|
let mut fctl = crate::FrameControl {
|
||||||
width: idat_width,
|
width,
|
||||||
height: idat_width, // same height and width
|
height: width,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut png = VecDeque::new();
|
let mut png = Vec::new();
|
||||||
write_png_sig(&mut png);
|
write_png_sig(&mut png);
|
||||||
write_rgba8_ihdr_with_width(&mut png, idat_width);
|
write_rgba8_ihdr_with_width(&mut png, width);
|
||||||
write_actl(
|
write_actl(
|
||||||
&mut png,
|
&mut png,
|
||||||
&crate::AnimationControl {
|
&crate::AnimationControl {
|
||||||
@ -2690,12 +2752,12 @@ mod tests {
|
|||||||
write_fdat(&mut png, 2, &fdat_data);
|
write_fdat(&mut png, 2, &fdat_data);
|
||||||
write_iend(&mut png);
|
write_iend(&mut png);
|
||||||
|
|
||||||
Decoder::new(png).read_info().unwrap()
|
Decoder::new(Cursor::new(png)).read_info().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains: IHDR, acTL,
|
/// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains: IHDR, acTL,
|
||||||
/// IDAT, fcTL, fdAT, fcTL, fdAT, IEND. (i.e. IDAT is *not* part of the animation)
|
/// IDAT, fcTL, fdAT, fcTL, fdAT, IEND. (i.e. IDAT is *not* part of the animation)
|
||||||
fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<VecDeque<u8>> {
|
fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
|
||||||
let width = 16;
|
let width = 16;
|
||||||
let frame_data = generate_rgba8_with_width_and_height(width, width);
|
let frame_data = generate_rgba8_with_width_and_height(width, width);
|
||||||
let mut fctl = crate::FrameControl {
|
let mut fctl = crate::FrameControl {
|
||||||
@ -2704,7 +2766,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut png = VecDeque::new();
|
let mut png = Vec::new();
|
||||||
write_png_sig(&mut png);
|
write_png_sig(&mut png);
|
||||||
write_rgba8_ihdr_with_width(&mut png, width);
|
write_rgba8_ihdr_with_width(&mut png, width);
|
||||||
write_actl(
|
write_actl(
|
||||||
@ -2723,10 +2785,10 @@ mod tests {
|
|||||||
write_fdat(&mut png, 3, &frame_data);
|
write_fdat(&mut png, 3, &frame_data);
|
||||||
write_iend(&mut png);
|
write_iend(&mut png);
|
||||||
|
|
||||||
Decoder::new(png).read_info().unwrap()
|
Decoder::new(Cursor::new(png)).read_info().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fctl_sequence_number(reader: &Reader<impl Read>) -> u32 {
|
fn get_fctl_sequence_number(reader: &Reader<impl BufRead + Seek>) -> u32 {
|
||||||
reader
|
reader
|
||||||
.info()
|
.info()
|
||||||
.frame_control
|
.frame_control
|
||||||
@ -2966,4 +3028,28 @@ mod tests {
|
|||||||
&err,
|
&err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_incorrect_trns_chunk_is_ignored() {
|
||||||
|
let png = {
|
||||||
|
let mut png = Vec::new();
|
||||||
|
write_png_sig(&mut png);
|
||||||
|
write_rgba8_ihdr_with_width(&mut png, 8);
|
||||||
|
write_chunk(&mut png, b"tRNS", &[12, 34, 56]);
|
||||||
|
write_chunk(
|
||||||
|
&mut png,
|
||||||
|
b"IDAT",
|
||||||
|
&generate_rgba8_with_width_and_height(8, 8),
|
||||||
|
);
|
||||||
|
write_iend(&mut png);
|
||||||
|
png
|
||||||
|
};
|
||||||
|
let decoder = Decoder::new(Cursor::new(&png));
|
||||||
|
let mut reader = decoder.read_info().unwrap();
|
||||||
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
|
assert!(reader.info().trns.is_none());
|
||||||
|
reader.next_frame(&mut buf).unwrap();
|
||||||
|
assert_eq!(3093270825, crc32fast::hash(&buf));
|
||||||
|
assert!(reader.info().trns.is_none());
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use super::stream::{DecodingError, FormatErrorInner};
|
use super::stream::{DecodingError, FormatErrorInner};
|
||||||
use crate::common::BytesPerPixel;
|
use crate::common::BytesPerPixel;
|
||||||
use crate::filter::{unfilter, FilterType};
|
use crate::filter::{unfilter, RowFilter};
|
||||||
|
|
||||||
// Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows.
|
// Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows.
|
||||||
pub(crate) struct UnfilteringBuffer {
|
pub(crate) struct UnfilteringBuffer {
|
||||||
@ -96,7 +96,7 @@ impl UnfilteringBuffer {
|
|||||||
debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1));
|
debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1));
|
||||||
|
|
||||||
// Get the filter type.
|
// Get the filter type.
|
||||||
let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format(
|
let filter = RowFilter::from_u8(row[0]).ok_or(DecodingError::Format(
|
||||||
FormatErrorInner::UnknownFilterMethod(row[0]).into(),
|
FormatErrorInner::UnknownFilterMethod(row[0]).into(),
|
||||||
))?;
|
))?;
|
||||||
let row = &mut row[1..rowlen];
|
let row = &mut row[1..rowlen];
|
@ -9,13 +9,14 @@ use flate2::write::ZlibEncoder;
|
|||||||
use crate::chunk::{self, ChunkType};
|
use crate::chunk::{self, ChunkType};
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
AnimationControl, BitDepth, BlendOp, BytesPerPixel, ColorType, Compression, DisposeOp,
|
AnimationControl, BitDepth, BlendOp, BytesPerPixel, ColorType, Compression, DisposeOp,
|
||||||
FrameControl, Info, ParameterError, ParameterErrorKind, PixelDimensions, ScaledFloat,
|
FrameControl, Info, ParameterError, ParameterErrorKind, PixelDimensions, ScaledFloat, Unit,
|
||||||
};
|
};
|
||||||
use crate::filter::{filter, AdaptiveFilterType, FilterType};
|
use crate::filter::{filter, Filter};
|
||||||
use crate::text_metadata::{
|
use crate::text_metadata::{
|
||||||
encode_iso_8859_1, EncodableTextChunk, ITXtChunk, TEXtChunk, TextEncodingError, ZTXtChunk,
|
encode_iso_8859_1, EncodableTextChunk, ITXtChunk, TEXtChunk, TextEncodingError, ZTXtChunk,
|
||||||
};
|
};
|
||||||
use crate::traits::WriteBytesExt;
|
use crate::traits::WriteBytesExt;
|
||||||
|
use crate::DeflateCompression;
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, EncodingError>;
|
pub type Result<T> = result::Result<T, EncodingError>;
|
||||||
|
|
||||||
@ -151,13 +152,13 @@ pub struct Encoder<'a, W: Write> {
|
|||||||
options: Options,
|
options: Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decoding options, internal type, forwarded to the Writer.
|
/// Encoding options, internal type, forwarded to the Writer.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Options {
|
struct Options {
|
||||||
filter: FilterType,
|
filter: Filter,
|
||||||
adaptive_filter: AdaptiveFilterType,
|
|
||||||
sep_def_img: bool,
|
sep_def_img: bool,
|
||||||
validate_sequence: bool,
|
validate_sequence: bool,
|
||||||
|
compression: DeflateCompression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, W: Write> Encoder<'a, W> {
|
impl<'a, W: Write> Encoder<'a, W> {
|
||||||
@ -265,18 +266,6 @@ impl<'a, W: Write> Encoder<'a, W> {
|
|||||||
self.info.source_chromaticities = Some(source_chromaticities);
|
self.info.source_chromaticities = Some(source_chromaticities);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark the image data as conforming to the SRGB color space with the specified rendering intent.
|
|
||||||
///
|
|
||||||
/// Matching source gamma and chromaticities chunks are added automatically.
|
|
||||||
/// Any manually specified source gamma, chromaticities, or ICC profiles will be ignored.
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[deprecated(note = "use set_source_srgb")]
|
|
||||||
pub fn set_srgb(&mut self, rendering_intent: super::SrgbRenderingIntent) {
|
|
||||||
self.info.set_source_srgb(rendering_intent);
|
|
||||||
self.info.source_gamma = Some(crate::srgb::substitute_gamma());
|
|
||||||
self.info.source_chromaticities = Some(crate::srgb::substitute_chromaticities());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mark the image data as conforming to the SRGB color space with the specified rendering intent.
|
/// Mark the image data as conforming to the SRGB color space with the specified rendering intent.
|
||||||
///
|
///
|
||||||
/// Any ICC profiles will be ignored.
|
/// Any ICC profiles will be ignored.
|
||||||
@ -308,31 +297,28 @@ impl<'a, W: Write> Encoder<'a, W> {
|
|||||||
self.info.bit_depth = depth;
|
self.info.bit_depth = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set compression parameters.
|
/// Set compression parameters, see [Compression] for the available options.
|
||||||
///
|
|
||||||
/// Accepts a `Compression` or any type that can transform into a `Compression`. Notably `deflate::Compression` and
|
|
||||||
/// `deflate::CompressionOptions` which "just work".
|
|
||||||
pub fn set_compression(&mut self, compression: Compression) {
|
pub fn set_compression(&mut self, compression: Compression) {
|
||||||
self.info.compression = compression;
|
self.set_deflate_compression(DeflateCompression::from_simple(compression));
|
||||||
|
self.set_filter(Filter::from_simple(compression));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides in-depth customization of DEFLATE compression options.
|
||||||
|
///
|
||||||
|
/// For a simpler selection of compression options see [Self::set_compression].
|
||||||
|
pub fn set_deflate_compression(&mut self, compression: DeflateCompression) {
|
||||||
|
self.options.compression = compression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the used filter type.
|
/// Set the used filter type.
|
||||||
///
|
///
|
||||||
/// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for
|
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||||
/// sample values based on the previous. For a potentially better compression ratio, at the
|
/// for each row of the image.
|
||||||
/// cost of more complex processing, try out [`FilterType::Paeth`].
|
|
||||||
pub fn set_filter(&mut self, filter: FilterType) {
|
|
||||||
self.options.filter = filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the adaptive filter type.
|
|
||||||
///
|
///
|
||||||
/// Adaptive filtering attempts to select the best filter for each line
|
/// You should only change this if you are after very fast compression,
|
||||||
/// based on heuristics which minimize the file size for compression rather
|
/// and either don't care about compression ratio or know exactly what works best for your images.
|
||||||
/// than use a single filter for the entire image. The default method is
|
pub fn set_filter(&mut self, filter: Filter) {
|
||||||
/// [`AdaptiveFilterType::NonAdaptive`].
|
self.options.filter = filter;
|
||||||
pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) {
|
|
||||||
self.options.adaptive_filter = adaptive_filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the fraction of time every frame is going to be displayed, in seconds.
|
/// Set the fraction of time every frame is going to be displayed, in seconds.
|
||||||
@ -495,7 +481,6 @@ struct PartialInfo {
|
|||||||
color_type: ColorType,
|
color_type: ColorType,
|
||||||
frame_control: Option<FrameControl>,
|
frame_control: Option<FrameControl>,
|
||||||
animation_control: Option<AnimationControl>,
|
animation_control: Option<AnimationControl>,
|
||||||
compression: Compression,
|
|
||||||
has_palette: bool,
|
has_palette: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,39 +493,25 @@ impl PartialInfo {
|
|||||||
color_type: info.color_type,
|
color_type: info.color_type,
|
||||||
frame_control: info.frame_control,
|
frame_control: info.frame_control,
|
||||||
animation_control: info.animation_control,
|
animation_control: info.animation_control,
|
||||||
compression: info.compression,
|
|
||||||
has_palette: info.palette.is_some(),
|
has_palette: info.palette.is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bpp_in_prediction(&self) -> BytesPerPixel {
|
fn bpp_in_prediction(&self) -> BytesPerPixel {
|
||||||
// Passthrough
|
BytesPerPixel::from_usize(self.bytes_per_pixel())
|
||||||
self.to_info().bpp_in_prediction()
|
}
|
||||||
|
|
||||||
|
fn bytes_per_pixel(&self) -> usize {
|
||||||
|
self.color_type.bytes_per_pixel(self.bit_depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_row_length(&self) -> usize {
|
fn raw_row_length(&self) -> usize {
|
||||||
// Passthrough
|
self.raw_row_length_from_width(self.width)
|
||||||
self.to_info().raw_row_length()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_row_length_from_width(&self, width: u32) -> usize {
|
fn raw_row_length_from_width(&self, width: u32) -> usize {
|
||||||
// Passthrough
|
self.color_type
|
||||||
self.to_info().raw_row_length_from_width(width)
|
.raw_row_length_from_width(self.bit_depth, width)
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts this partial info to an owned Info struct,
|
|
||||||
/// setting missing values to their defaults
|
|
||||||
fn to_info(&self) -> Info<'static> {
|
|
||||||
Info {
|
|
||||||
width: self.width,
|
|
||||||
height: self.height,
|
|
||||||
bit_depth: self.bit_depth,
|
|
||||||
color_type: self.color_type,
|
|
||||||
frame_control: self.frame_control,
|
|
||||||
animation_control: self.animation_control,
|
|
||||||
compression: self.compression,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,17 +560,100 @@ impl<W: Write> Writer<W> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?; // PNG signature
|
self.encode_header(info)?;
|
||||||
#[allow(deprecated)]
|
|
||||||
info.encode(&mut self.w)?;
|
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encode PNG signature, IHDR, and then chunks that were added to the `Info`
|
||||||
|
fn encode_header(&mut self, info: &Info<'_>) -> Result<()> {
|
||||||
|
self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?; // PNG signature
|
||||||
|
|
||||||
|
// Encode the IHDR chunk
|
||||||
|
let mut data = [0; 13];
|
||||||
|
data[..4].copy_from_slice(&info.width.to_be_bytes());
|
||||||
|
data[4..8].copy_from_slice(&info.height.to_be_bytes());
|
||||||
|
data[8] = info.bit_depth as u8;
|
||||||
|
data[9] = info.color_type as u8;
|
||||||
|
data[12] = info.interlaced as u8;
|
||||||
|
self.write_chunk(chunk::IHDR, &data)?;
|
||||||
|
|
||||||
|
// Encode the pHYs chunk
|
||||||
|
if let Some(pd) = info.pixel_dims {
|
||||||
|
let mut phys_data = [0; 9];
|
||||||
|
phys_data[0..4].copy_from_slice(&pd.xppu.to_be_bytes());
|
||||||
|
phys_data[4..8].copy_from_slice(&pd.yppu.to_be_bytes());
|
||||||
|
match pd.unit {
|
||||||
|
Unit::Meter => phys_data[8] = 1,
|
||||||
|
Unit::Unspecified => phys_data[8] = 0,
|
||||||
|
}
|
||||||
|
self.write_chunk(chunk::pHYs, &phys_data)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If specified, the sRGB information overrides the source gamma and chromaticities.
|
||||||
|
if let Some(srgb) = &info.srgb {
|
||||||
|
srgb.encode(&mut self.w)?;
|
||||||
|
|
||||||
|
// gAMA and cHRM are optional, for backwards compatibility
|
||||||
|
let srgb_gamma = crate::srgb::substitute_gamma();
|
||||||
|
if Some(srgb_gamma) == info.source_gamma {
|
||||||
|
srgb_gamma.encode_gama(&mut self.w)?
|
||||||
|
}
|
||||||
|
let srgb_chromaticities = crate::srgb::substitute_chromaticities();
|
||||||
|
if Some(srgb_chromaticities) == info.source_chromaticities {
|
||||||
|
srgb_chromaticities.encode(&mut self.w)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(gma) = info.source_gamma {
|
||||||
|
gma.encode_gama(&mut self.w)?
|
||||||
|
}
|
||||||
|
if let Some(chrms) = info.source_chromaticities {
|
||||||
|
chrms.encode(&mut self.w)?;
|
||||||
|
}
|
||||||
|
if let Some(iccp) = &info.icc_profile {
|
||||||
|
self.write_iccp_chunk("_", iccp)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(exif) = &info.exif_metadata {
|
||||||
|
self.write_chunk(chunk::eXIf, exif)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(actl) = info.animation_control {
|
||||||
|
actl.encode(&mut self.w)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The position of the PLTE chunk is important, it must come before the tRNS chunk and after
|
||||||
|
// many of the other metadata chunks.
|
||||||
|
if let Some(p) = &info.palette {
|
||||||
|
self.write_chunk(chunk::PLTE, p)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(t) = &info.trns {
|
||||||
|
self.write_chunk(chunk::tRNS, t)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for text_chunk in &info.uncompressed_latin1_text {
|
||||||
|
self.write_text_chunk(text_chunk)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for text_chunk in &info.compressed_latin1_text {
|
||||||
|
self.write_text_chunk(text_chunk)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for text_chunk in &info.utf8_text {
|
||||||
|
self.write_text_chunk(text_chunk)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Write a raw chunk of PNG data.
|
/// Write a raw chunk of PNG data.
|
||||||
///
|
///
|
||||||
/// The chunk will have its CRC calculated and correctly. The data is not filtered in any way,
|
/// This function calculates the required CRC sum so this should not be included in the input
|
||||||
/// but the chunk needs to be short enough to have its length encoded correctly.
|
/// `data`, otherwise the data is not filtered in any way. This function returns an error if
|
||||||
|
/// the length of `data` can't be parsed as a `u32` though the length of the chunk data should
|
||||||
|
/// not exceed `i32::MAX` or 2,147,483,647.
|
||||||
pub fn write_chunk(&mut self, name: ChunkType, data: &[u8]) -> Result<()> {
|
pub fn write_chunk(&mut self, name: ChunkType, data: &[u8]) -> Result<()> {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@ -615,6 +669,31 @@ impl<W: Write> Writer<W> {
|
|||||||
text_chunk.encode(&mut self.w)
|
text_chunk.encode(&mut self.w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_iccp_chunk(&mut self, profile_name: &str, icc_profile: &[u8]) -> Result<()> {
|
||||||
|
let profile_name = encode_iso_8859_1(profile_name)?;
|
||||||
|
if profile_name.len() < 1 || profile_name.len() > 79 {
|
||||||
|
return Err(TextEncodingError::InvalidKeywordSize.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let estimated_compressed_size = icc_profile.len() * 3 / 4;
|
||||||
|
let chunk_size = profile_name
|
||||||
|
.len()
|
||||||
|
.checked_add(2) // string NUL + compression type. Checked add optimizes out later Vec reallocations.
|
||||||
|
.and_then(|s| s.checked_add(estimated_compressed_size))
|
||||||
|
.ok_or(EncodingError::LimitsExceeded)?;
|
||||||
|
|
||||||
|
let mut data = Vec::new();
|
||||||
|
data.try_reserve_exact(chunk_size)
|
||||||
|
.map_err(|_| EncodingError::LimitsExceeded)?;
|
||||||
|
|
||||||
|
data.extend(profile_name.into_iter().chain([0, 0]));
|
||||||
|
|
||||||
|
let mut encoder = ZlibEncoder::new(data, flate2::Compression::default());
|
||||||
|
encoder.write_all(icc_profile)?;
|
||||||
|
|
||||||
|
self.write_chunk(chunk::iCCP, &encoder.finish()?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if we should allow writing another image.
|
/// Check if we should allow writing another image.
|
||||||
fn validate_new_image(&self) -> Result<()> {
|
fn validate_new_image(&self) -> Result<()> {
|
||||||
if !self.options.validate_sequence {
|
if !self.options.validate_sequence {
|
||||||
@ -692,22 +771,23 @@ impl<W: Write> Writer<W> {
|
|||||||
|
|
||||||
let bpp = self.info.bpp_in_prediction();
|
let bpp = self.info.bpp_in_prediction();
|
||||||
let filter_method = self.options.filter;
|
let filter_method = self.options.filter;
|
||||||
let adaptive_method = self.options.adaptive_filter;
|
|
||||||
|
|
||||||
let zlib_encoded = match self.info.compression {
|
let zlib_encoded = match self.options.compression {
|
||||||
Compression::Fast => {
|
DeflateCompression::NoCompression => {
|
||||||
|
let mut compressor =
|
||||||
|
fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?;
|
||||||
|
for line in data.chunks(in_len) {
|
||||||
|
compressor.write_data(&[0])?;
|
||||||
|
compressor.write_data(line)?;
|
||||||
|
}
|
||||||
|
compressor.finish()?.into_inner()
|
||||||
|
}
|
||||||
|
DeflateCompression::FdeflateUltraFast => {
|
||||||
let mut compressor = fdeflate::Compressor::new(std::io::Cursor::new(Vec::new()))?;
|
let mut compressor = fdeflate::Compressor::new(std::io::Cursor::new(Vec::new()))?;
|
||||||
|
|
||||||
let mut current = vec![0; in_len + 1];
|
let mut current = vec![0; in_len + 1];
|
||||||
for line in data.chunks(in_len) {
|
for line in data.chunks(in_len) {
|
||||||
let filter_type = filter(
|
let filter_type = filter(filter_method, bpp, prev, line, &mut current[1..]);
|
||||||
filter_method,
|
|
||||||
adaptive_method,
|
|
||||||
bpp,
|
|
||||||
prev,
|
|
||||||
line,
|
|
||||||
&mut current[1..],
|
|
||||||
);
|
|
||||||
|
|
||||||
current[0] = filter_type as u8;
|
current[0] = filter_type as u8;
|
||||||
compressor.write_data(¤t)?;
|
compressor.write_data(¤t)?;
|
||||||
@ -721,10 +801,7 @@ impl<W: Write> Writer<W> {
|
|||||||
// Write uncompressed data since the result from fast compression would take
|
// Write uncompressed data since the result from fast compression would take
|
||||||
// more space than that.
|
// more space than that.
|
||||||
//
|
//
|
||||||
// We always use FilterType::NoFilter here regardless of the filter method
|
// This is essentially a fallback to NoCompression.
|
||||||
// requested by the user. Doing filtering again would only add performance
|
|
||||||
// cost for both encoding and subsequent decoding, without improving the
|
|
||||||
// compression ratio.
|
|
||||||
let mut compressor =
|
let mut compressor =
|
||||||
fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?;
|
fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?;
|
||||||
for line in data.chunks(in_len) {
|
for line in data.chunks(in_len) {
|
||||||
@ -736,19 +813,13 @@ impl<W: Write> Writer<W> {
|
|||||||
compressed
|
compressed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
DeflateCompression::Level(level) => {
|
||||||
let mut current = vec![0; in_len];
|
let mut current = vec![0; in_len];
|
||||||
|
|
||||||
let mut zlib = ZlibEncoder::new(Vec::new(), self.info.compression.to_options());
|
let mut zlib =
|
||||||
|
ZlibEncoder::new(Vec::new(), flate2::Compression::new(u32::from(level)));
|
||||||
for line in data.chunks(in_len) {
|
for line in data.chunks(in_len) {
|
||||||
let filter_type = filter(
|
let filter_type = filter(filter_method, bpp, prev, line, &mut current);
|
||||||
filter_method,
|
|
||||||
adaptive_method,
|
|
||||||
bpp,
|
|
||||||
prev,
|
|
||||||
line,
|
|
||||||
&mut current,
|
|
||||||
);
|
|
||||||
|
|
||||||
zlib.write_all(&[filter_type as u8])?;
|
zlib.write_all(&[filter_type as u8])?;
|
||||||
zlib.write_all(¤t)?;
|
zlib.write_all(¤t)?;
|
||||||
@ -818,25 +889,17 @@ impl<W: Write> Writer<W> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the used filter type for the following frames.
|
/// Set the used filter type.
|
||||||
///
|
///
|
||||||
/// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for
|
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||||
/// sample values based on the previous. For a potentially better compression ratio, at the
|
/// for each row of the image.
|
||||||
/// cost of more complex processing, try out [`FilterType::Paeth`].
|
///
|
||||||
pub fn set_filter(&mut self, filter: FilterType) {
|
/// You should only change this if you are after very fast compression,
|
||||||
|
/// and either don't care about compression ratio or know exactly what works best for your images.
|
||||||
|
pub fn set_filter(&mut self, filter: Filter) {
|
||||||
self.options.filter = filter;
|
self.options.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the adaptive filter type for the following frames.
|
|
||||||
///
|
|
||||||
/// Adaptive filtering attempts to select the best filter for each line
|
|
||||||
/// based on heuristics which minimize the file size for compression rather
|
|
||||||
/// than use a single filter for the entire image. The default method is
|
|
||||||
/// [`AdaptiveFilterType::NonAdaptive`].
|
|
||||||
pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) {
|
|
||||||
self.options.adaptive_filter = adaptive_filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the fraction of time the following frames are going to be displayed,
|
/// Set the fraction of time the following frames are going to be displayed,
|
||||||
/// in seconds
|
/// in seconds
|
||||||
///
|
///
|
||||||
@ -1055,36 +1118,6 @@ impl<W: Write> Drop for Writer<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be moved to Writer after `Info::encoding` is gone
|
|
||||||
pub(crate) fn write_iccp_chunk<W: Write>(
|
|
||||||
w: &mut W,
|
|
||||||
profile_name: &str,
|
|
||||||
icc_profile: &[u8],
|
|
||||||
) -> Result<()> {
|
|
||||||
let profile_name = encode_iso_8859_1(profile_name)?;
|
|
||||||
if profile_name.len() < 1 || profile_name.len() > 79 {
|
|
||||||
return Err(TextEncodingError::InvalidKeywordSize.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let estimated_compressed_size = icc_profile.len() * 3 / 4;
|
|
||||||
let chunk_size = profile_name
|
|
||||||
.len()
|
|
||||||
.checked_add(2) // string NUL + compression type. Checked add optimizes out later Vec reallocations.
|
|
||||||
.and_then(|s| s.checked_add(estimated_compressed_size))
|
|
||||||
.ok_or(EncodingError::LimitsExceeded)?;
|
|
||||||
|
|
||||||
let mut data = Vec::new();
|
|
||||||
data.try_reserve_exact(chunk_size)
|
|
||||||
.map_err(|_| EncodingError::LimitsExceeded)?;
|
|
||||||
|
|
||||||
data.extend(profile_name.into_iter().chain([0, 0]));
|
|
||||||
|
|
||||||
let mut encoder = ZlibEncoder::new(data, flate2::Compression::default());
|
|
||||||
encoder.write_all(icc_profile)?;
|
|
||||||
|
|
||||||
write_chunk(w, chunk::iCCP, &encoder.finish()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ChunkOutput<'a, W: Write> {
|
enum ChunkOutput<'a, W: Write> {
|
||||||
Borrowed(&'a mut Writer<W>),
|
Borrowed(&'a mut Writer<W>),
|
||||||
Owned(Writer<W>),
|
Owned(Writer<W>),
|
||||||
@ -1342,10 +1375,9 @@ pub struct StreamWriter<'a, W: Write> {
|
|||||||
height: u32,
|
height: u32,
|
||||||
|
|
||||||
bpp: BytesPerPixel,
|
bpp: BytesPerPixel,
|
||||||
filter: FilterType,
|
filter: Filter,
|
||||||
adaptive_filter: AdaptiveFilterType,
|
|
||||||
fctl: Option<FrameControl>,
|
fctl: Option<FrameControl>,
|
||||||
compression: Compression,
|
compression: DeflateCompression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, W: Write> StreamWriter<'a, W> {
|
impl<'a, W: Write> StreamWriter<'a, W> {
|
||||||
@ -1354,21 +1386,20 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
frame_control: fctl,
|
frame_control: fctl,
|
||||||
compression,
|
|
||||||
..
|
..
|
||||||
} = writer.info;
|
} = writer.info;
|
||||||
|
|
||||||
let bpp = writer.info.bpp_in_prediction();
|
let bpp = writer.info.bpp_in_prediction();
|
||||||
let in_len = writer.info.raw_row_length() - 1;
|
let in_len = writer.info.raw_row_length() - 1;
|
||||||
let filter = writer.options.filter;
|
let filter = writer.options.filter;
|
||||||
let adaptive_filter = writer.options.adaptive_filter;
|
let compression = writer.options.compression;
|
||||||
let prev_buf = vec![0; in_len];
|
let prev_buf = vec![0; in_len];
|
||||||
let curr_buf = vec![0; in_len];
|
let curr_buf = vec![0; in_len];
|
||||||
|
|
||||||
let mut chunk_writer = ChunkWriter::new(writer, buf_len);
|
let mut chunk_writer = ChunkWriter::new(writer, buf_len);
|
||||||
let (line_len, to_write) = chunk_writer.next_frame_info();
|
let (line_len, to_write) = chunk_writer.next_frame_info();
|
||||||
chunk_writer.write_header()?;
|
chunk_writer.write_header()?;
|
||||||
let zlib = ZlibEncoder::new(chunk_writer, compression.to_options());
|
let zlib = ZlibEncoder::new(chunk_writer, compression.closest_flate2_level());
|
||||||
|
|
||||||
Ok(StreamWriter {
|
Ok(StreamWriter {
|
||||||
writer: Wrapper::Zlib(zlib),
|
writer: Wrapper::Zlib(zlib),
|
||||||
@ -1379,7 +1410,6 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
|||||||
filter,
|
filter,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
adaptive_filter,
|
|
||||||
line_len,
|
line_len,
|
||||||
to_write,
|
to_write,
|
||||||
fctl,
|
fctl,
|
||||||
@ -1387,29 +1417,17 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the used filter type for the next frame.
|
/// Set the used filter type.
|
||||||
///
|
///
|
||||||
/// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for
|
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||||
/// sample values based on the previous.
|
/// for each row of the image.
|
||||||
///
|
///
|
||||||
/// For optimal compression ratio you should enable adaptive filtering
|
/// You should only change this if you are after very fast compression,
|
||||||
/// instead of setting a single filter for the entire image, see
|
/// and either don't care about compression ratio or know exactly what works best for your images.
|
||||||
/// [set_adaptive_filter](Self::set_adaptive_filter).
|
pub fn set_filter(&mut self, filter: Filter) {
|
||||||
pub fn set_filter(&mut self, filter: FilterType) {
|
|
||||||
self.filter = filter;
|
self.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the adaptive filter type for the next frame.
|
|
||||||
///
|
|
||||||
/// Adaptive filtering attempts to select the best filter for each line
|
|
||||||
/// based on heuristics which minimize the file size for compression rather
|
|
||||||
/// than use a single filter for the entire image.
|
|
||||||
///
|
|
||||||
/// The default method is [`AdaptiveFilterType::NonAdaptive`].
|
|
||||||
pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) {
|
|
||||||
self.adaptive_filter = adaptive_filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the fraction of time the following frames are going to be displayed,
|
/// Set the fraction of time the following frames are going to be displayed,
|
||||||
/// in seconds
|
/// in seconds
|
||||||
///
|
///
|
||||||
@ -1611,7 +1629,7 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
|||||||
// now it can be taken because the next statements cannot cause any errors
|
// now it can be taken because the next statements cannot cause any errors
|
||||||
match self.writer.take() {
|
match self.writer.take() {
|
||||||
Wrapper::Chunk(wrt) => {
|
Wrapper::Chunk(wrt) => {
|
||||||
let encoder = ZlibEncoder::new(wrt, self.compression.to_options());
|
let encoder = ZlibEncoder::new(wrt, self.compression.closest_flate2_level());
|
||||||
self.writer = Wrapper::Zlib(encoder);
|
self.writer = Wrapper::Zlib(encoder);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -1659,7 +1677,6 @@ impl<'a, W: Write> Write for StreamWriter<'a, W> {
|
|||||||
let mut filtered = vec![0; self.curr_buf.len()];
|
let mut filtered = vec![0; self.curr_buf.len()];
|
||||||
let filter_type = filter(
|
let filter_type = filter(
|
||||||
self.filter,
|
self.filter,
|
||||||
self.adaptive_filter,
|
|
||||||
self.bpp,
|
self.bpp,
|
||||||
&self.prev_buf,
|
&self.prev_buf,
|
||||||
&self.curr_buf,
|
&self.curr_buf,
|
||||||
@ -1707,39 +1724,30 @@ impl<W: Write> Drop for StreamWriter<'_, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mod to encapsulate the converters depending on the `deflate` crate.
|
|
||||||
///
|
|
||||||
/// Since this only contains trait impls, there is no need to make this public, they are simply
|
|
||||||
/// available when the mod is compiled as well.
|
|
||||||
impl Compression {
|
|
||||||
fn to_options(self) -> flate2::Compression {
|
|
||||||
#[allow(deprecated)]
|
|
||||||
match self {
|
|
||||||
Compression::Default => flate2::Compression::default(),
|
|
||||||
Compression::Fast => flate2::Compression::fast(),
|
|
||||||
Compression::Best => flate2::Compression::best(),
|
|
||||||
#[allow(deprecated)]
|
|
||||||
Compression::Huffman => flate2::Compression::none(),
|
|
||||||
#[allow(deprecated)]
|
|
||||||
Compression::Rle => flate2::Compression::none(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Decoder;
|
use crate::Decoder;
|
||||||
|
|
||||||
|
use io::BufReader;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roundtrip() {
|
fn roundtrip1() {
|
||||||
|
roundtrip_inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip2() {
|
||||||
|
roundtrip_inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roundtrip_inner() {
|
||||||
// More loops = more random testing, but also more test wait time
|
// More loops = more random testing, but also more test wait time
|
||||||
for _ in 0..10 {
|
for _ in 0..5 {
|
||||||
for path in glob::glob("tests/pngsuite/*.png")
|
for path in glob::glob("tests/pngsuite/*.png")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|r| r.unwrap())
|
.map(|r| r.unwrap())
|
||||||
@ -1750,42 +1758,55 @@ mod tests {
|
|||||||
}
|
}
|
||||||
eprintln!("{}", path.display());
|
eprintln!("{}", path.display());
|
||||||
// Decode image
|
// Decode image
|
||||||
let decoder = Decoder::new(File::open(path).unwrap());
|
let decoder = Decoder::new(BufReader::new(File::open(path).unwrap()));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
let info = reader.next_frame(&mut buf).unwrap();
|
let info = reader.next_frame(&mut buf).unwrap();
|
||||||
// Encode decoded image
|
use DeflateCompression::*;
|
||||||
let mut out = Vec::new();
|
for compression in [NoCompression, FdeflateUltraFast, Level(4)] {
|
||||||
{
|
// Encode decoded image
|
||||||
let mut wrapper = RandomChunkWriter {
|
let mut out = Vec::new();
|
||||||
rng: thread_rng(),
|
{
|
||||||
w: &mut out,
|
let mut wrapper = RandomChunkWriter {
|
||||||
};
|
rng: thread_rng(),
|
||||||
|
w: &mut out,
|
||||||
|
};
|
||||||
|
|
||||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||||
encoder.set_color(info.color_type);
|
encoder.set_color(info.color_type);
|
||||||
encoder.set_depth(info.bit_depth);
|
encoder.set_depth(info.bit_depth);
|
||||||
if let Some(palette) = &reader.info().palette {
|
encoder.set_deflate_compression(compression);
|
||||||
encoder.set_palette(palette.clone());
|
if let Some(palette) = &reader.info().palette {
|
||||||
|
encoder.set_palette(palette.clone());
|
||||||
|
}
|
||||||
|
let mut encoder = encoder.write_header().unwrap();
|
||||||
|
encoder.write_image_data(&buf).unwrap();
|
||||||
}
|
}
|
||||||
let mut encoder = encoder.write_header().unwrap();
|
// Decode encoded decoded image
|
||||||
encoder.write_image_data(&buf).unwrap();
|
let decoder = Decoder::new(Cursor::new(&*out));
|
||||||
|
let mut reader = decoder.read_info().unwrap();
|
||||||
|
let mut buf2 = vec![0; reader.output_buffer_size()];
|
||||||
|
reader.next_frame(&mut buf2).unwrap();
|
||||||
|
// check if the encoded image is ok:
|
||||||
|
assert_eq!(buf, buf2);
|
||||||
}
|
}
|
||||||
// Decode encoded decoded image
|
|
||||||
let decoder = Decoder::new(&*out);
|
|
||||||
let mut reader = decoder.read_info().unwrap();
|
|
||||||
let mut buf2 = vec![0; reader.output_buffer_size()];
|
|
||||||
reader.next_frame(&mut buf2).unwrap();
|
|
||||||
// check if the encoded image is ok:
|
|
||||||
assert_eq!(buf, buf2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roundtrip_stream() {
|
fn roundtrip_stream1() {
|
||||||
|
roundtrip_stream_inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_stream2() {
|
||||||
|
roundtrip_stream_inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roundtrip_stream_inner() {
|
||||||
// More loops = more random testing, but also more test wait time
|
// More loops = more random testing, but also more test wait time
|
||||||
for _ in 0..10 {
|
for _ in 0..5 {
|
||||||
for path in glob::glob("tests/pngsuite/*.png")
|
for path in glob::glob("tests/pngsuite/*.png")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|r| r.unwrap())
|
.map(|r| r.unwrap())
|
||||||
@ -1795,41 +1816,45 @@ mod tests {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Decode image
|
// Decode image
|
||||||
let decoder = Decoder::new(File::open(path).unwrap());
|
let decoder = Decoder::new(BufReader::new(File::open(path).unwrap()));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
let info = reader.next_frame(&mut buf).unwrap();
|
let info = reader.next_frame(&mut buf).unwrap();
|
||||||
// Encode decoded image
|
use DeflateCompression::*;
|
||||||
let mut out = Vec::new();
|
for compression in [NoCompression, FdeflateUltraFast, Level(4)] {
|
||||||
{
|
// Encode decoded image
|
||||||
let mut wrapper = RandomChunkWriter {
|
let mut out = Vec::new();
|
||||||
rng: thread_rng(),
|
{
|
||||||
w: &mut out,
|
let mut wrapper = RandomChunkWriter {
|
||||||
};
|
rng: thread_rng(),
|
||||||
|
w: &mut out,
|
||||||
|
};
|
||||||
|
|
||||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||||
encoder.set_color(info.color_type);
|
encoder.set_color(info.color_type);
|
||||||
encoder.set_depth(info.bit_depth);
|
encoder.set_depth(info.bit_depth);
|
||||||
if let Some(palette) = &reader.info().palette {
|
encoder.set_deflate_compression(compression);
|
||||||
encoder.set_palette(palette.clone());
|
if let Some(palette) = &reader.info().palette {
|
||||||
|
encoder.set_palette(palette.clone());
|
||||||
|
}
|
||||||
|
let mut encoder = encoder.write_header().unwrap();
|
||||||
|
let mut stream_writer = encoder.stream_writer().unwrap();
|
||||||
|
|
||||||
|
let mut outer_wrapper = RandomChunkWriter {
|
||||||
|
rng: thread_rng(),
|
||||||
|
w: &mut stream_writer,
|
||||||
|
};
|
||||||
|
|
||||||
|
outer_wrapper.write_all(&buf).unwrap();
|
||||||
}
|
}
|
||||||
let mut encoder = encoder.write_header().unwrap();
|
// Decode encoded decoded image
|
||||||
let mut stream_writer = encoder.stream_writer().unwrap();
|
let decoder = Decoder::new(Cursor::new(&*out));
|
||||||
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut outer_wrapper = RandomChunkWriter {
|
let mut buf2 = vec![0; reader.output_buffer_size()];
|
||||||
rng: thread_rng(),
|
reader.next_frame(&mut buf2).unwrap();
|
||||||
w: &mut stream_writer,
|
// check if the encoded image is ok:
|
||||||
};
|
assert_eq!(buf, buf2);
|
||||||
|
|
||||||
outer_wrapper.write_all(&buf).unwrap();
|
|
||||||
}
|
}
|
||||||
// Decode encoded decoded image
|
|
||||||
let decoder = Decoder::new(&*out);
|
|
||||||
let mut reader = decoder.read_info().unwrap();
|
|
||||||
let mut buf2 = vec![0; reader.output_buffer_size()];
|
|
||||||
reader.next_frame(&mut buf2).unwrap();
|
|
||||||
// check if the encoded image is ok:
|
|
||||||
assert_eq!(buf, buf2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1839,7 +1864,7 @@ mod tests {
|
|||||||
for &bit_depth in &[1u8, 2, 4, 8] {
|
for &bit_depth in &[1u8, 2, 4, 8] {
|
||||||
// Do a reference decoding, choose a fitting palette image from pngsuite
|
// Do a reference decoding, choose a fitting palette image from pngsuite
|
||||||
let path = format!("tests/pngsuite/basn3p0{}.png", bit_depth);
|
let path = format!("tests/pngsuite/basn3p0{}.png", bit_depth);
|
||||||
let decoder = Decoder::new(File::open(&path).unwrap());
|
let decoder = Decoder::new(BufReader::new(File::open(&path).unwrap()));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
|
|
||||||
let mut decoded_pixels = vec![0; reader.output_buffer_size()];
|
let mut decoded_pixels = vec![0; reader.output_buffer_size()];
|
||||||
@ -1864,7 +1889,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode re-encoded image
|
// Decode re-encoded image
|
||||||
let decoder = Decoder::new(&*out);
|
let decoder = Decoder::new(Cursor::new(&*out));
|
||||||
let mut reader = decoder.read_info().unwrap();
|
let mut reader = decoder.read_info().unwrap();
|
||||||
let mut redecoded = vec![0; reader.output_buffer_size()];
|
let mut redecoded = vec![0; reader.output_buffer_size()];
|
||||||
reader.next_frame(&mut redecoded).unwrap();
|
reader.next_frame(&mut redecoded).unwrap();
|
||||||
@ -2056,7 +2081,7 @@ mod tests {
|
|||||||
fn all_filters_roundtrip() -> io::Result<()> {
|
fn all_filters_roundtrip() -> io::Result<()> {
|
||||||
let pixel: Vec<_> = (0..48).collect();
|
let pixel: Vec<_> = (0..48).collect();
|
||||||
|
|
||||||
let roundtrip = |filter: FilterType| -> io::Result<()> {
|
let roundtrip = |filter: Filter| -> io::Result<()> {
|
||||||
let mut buffer = vec![];
|
let mut buffer = vec![];
|
||||||
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
||||||
encoder.set_depth(BitDepth::Eight);
|
encoder.set_depth(BitDepth::Eight);
|
||||||
@ -2076,11 +2101,11 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
roundtrip(FilterType::NoFilter)?;
|
roundtrip(Filter::NoFilter)?;
|
||||||
roundtrip(FilterType::Sub)?;
|
roundtrip(Filter::Sub)?;
|
||||||
roundtrip(FilterType::Up)?;
|
roundtrip(Filter::Up)?;
|
||||||
roundtrip(FilterType::Avg)?;
|
roundtrip(Filter::Avg)?;
|
||||||
roundtrip(FilterType::Paeth)?;
|
roundtrip(Filter::Paeth)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -2094,7 +2119,7 @@ mod tests {
|
|||||||
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
||||||
encoder.set_depth(BitDepth::Eight);
|
encoder.set_depth(BitDepth::Eight);
|
||||||
encoder.set_color(ColorType::Rgb);
|
encoder.set_color(ColorType::Rgb);
|
||||||
encoder.set_filter(FilterType::Avg);
|
encoder.set_filter(Filter::Avg);
|
||||||
if let Some(gamma) = gamma {
|
if let Some(gamma) = gamma {
|
||||||
encoder.set_source_gamma(gamma);
|
encoder.set_source_gamma(gamma);
|
||||||
}
|
}
|
||||||
@ -2103,7 +2128,7 @@ mod tests {
|
|||||||
let decoder = crate::Decoder::new(Cursor::new(buffer));
|
let decoder = crate::Decoder::new(Cursor::new(buffer));
|
||||||
let mut reader = decoder.read_info()?;
|
let mut reader = decoder.read_info()?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
reader.info().source_gamma,
|
reader.info().gamma(),
|
||||||
gamma,
|
gamma,
|
||||||
"Deviation with gamma {:?}",
|
"Deviation with gamma {:?}",
|
||||||
gamma
|
gamma
|
||||||
@ -2318,7 +2343,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut encoder = Encoder::new(&mut cursor, 8, 8);
|
let mut encoder = Encoder::new(&mut cursor, 8, 8);
|
||||||
encoder.set_color(ColorType::Rgba);
|
encoder.set_color(ColorType::Rgba);
|
||||||
encoder.set_filter(FilterType::Paeth);
|
encoder.set_filter(Filter::Paeth);
|
||||||
let mut writer = encoder.write_header()?;
|
let mut writer = encoder.write_header()?;
|
||||||
let mut stream = writer.stream_writer()?;
|
let mut stream = writer.stream_writer()?;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
use crate::common::BytesPerPixel;
|
use crate::{common::BytesPerPixel, Compression};
|
||||||
|
|
||||||
/// SIMD helpers for `fn unfilter`
|
/// SIMD helpers for `fn unfilter`
|
||||||
///
|
///
|
||||||
@ -60,7 +60,7 @@ mod simd {
|
|||||||
out.into()
|
out.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Memory of previous pixels (as needed to unfilter `FilterType::Paeth`).
|
/// Memory of previous pixels (as needed to unfilter `Filter::Paeth`).
|
||||||
/// See also https://www.w3.org/TR/png/#filter-byte-positions
|
/// See also https://www.w3.org/TR/png/#filter-byte-positions
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PaethState<T, const N: usize>
|
struct PaethState<T, const N: usize>
|
||||||
@ -75,7 +75,7 @@ mod simd {
|
|||||||
a: Simd<T, N>,
|
a: Simd<T, N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutates `x` as needed to unfilter `FilterType::Paeth`.
|
/// Mutates `x` as needed to unfilter `Filter::Paeth`.
|
||||||
///
|
///
|
||||||
/// `b` is the current pixel in the previous row. `x` is the current pixel in the current row.
|
/// `b` is the current pixel in the previous row. `x` is the current pixel in the current row.
|
||||||
/// See also https://www.w3.org/TR/png/#filter-byte-positions
|
/// See also https://www.w3.org/TR/png/#filter-byte-positions
|
||||||
@ -124,7 +124,7 @@ mod simd {
|
|||||||
dest[0..3].copy_from_slice(&src.to_array()[0..3])
|
dest[0..3].copy_from_slice(&src.to_array()[0..3])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Undoes `FilterType::Paeth` for `BytesPerPixel::Three`.
|
/// Undoes `Filter::Paeth` for `BytesPerPixel::Three`.
|
||||||
pub fn unfilter_paeth3(mut prev_row: &[u8], mut curr_row: &mut [u8]) {
|
pub fn unfilter_paeth3(mut prev_row: &[u8], mut curr_row: &mut [u8]) {
|
||||||
debug_assert_eq!(prev_row.len(), curr_row.len());
|
debug_assert_eq!(prev_row.len(), curr_row.len());
|
||||||
debug_assert_eq!(prev_row.len() % 3, 0);
|
debug_assert_eq!(prev_row.len() % 3, 0);
|
||||||
@ -155,7 +155,7 @@ mod simd {
|
|||||||
store3(x, curr_row);
|
store3(x, curr_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Undoes `FilterType::Paeth` for `BytesPerPixel::Four` and `BytesPerPixel::Eight`.
|
/// Undoes `Filter::Paeth` for `BytesPerPixel::Four` and `BytesPerPixel::Eight`.
|
||||||
///
|
///
|
||||||
/// This function calculates the Paeth predictor entirely in `Simd<u8, N>`
|
/// This function calculates the Paeth predictor entirely in `Simd<u8, N>`
|
||||||
/// without converting to an intermediate `Simd<i16, N>`. Doing so avoids
|
/// without converting to an intermediate `Simd<i16, N>`. Doing so avoids
|
||||||
@ -187,7 +187,7 @@ mod simd {
|
|||||||
dest[0..6].copy_from_slice(&src.to_array()[0..6])
|
dest[0..6].copy_from_slice(&src.to_array()[0..6])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Undoes `FilterType::Paeth` for `BytesPerPixel::Six`.
|
/// Undoes `Filter::Paeth` for `BytesPerPixel::Six`.
|
||||||
pub fn unfilter_paeth6(mut prev_row: &[u8], mut curr_row: &mut [u8]) {
|
pub fn unfilter_paeth6(mut prev_row: &[u8], mut curr_row: &mut [u8]) {
|
||||||
debug_assert_eq!(prev_row.len(), curr_row.len());
|
debug_assert_eq!(prev_row.len(), curr_row.len());
|
||||||
debug_assert_eq!(prev_row.len() % 6, 0);
|
debug_assert_eq!(prev_row.len() % 6, 0);
|
||||||
@ -226,9 +226,53 @@ mod simd {
|
|||||||
/// this does not operate on pixels but on raw bytes of a scanline.
|
/// this does not operate on pixels but on raw bytes of a scanline.
|
||||||
///
|
///
|
||||||
/// Details on how each filter works can be found in the [PNG Book](http://www.libpng.org/pub/png/book/chapter09.html).
|
/// Details on how each filter works can be found in the [PNG Book](http://www.libpng.org/pub/png/book/chapter09.html).
|
||||||
|
///
|
||||||
|
/// The default filter is `Adaptive`, which uses heuristics to select the best filter for every row.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Filter {
|
||||||
|
NoFilter,
|
||||||
|
Sub,
|
||||||
|
Up,
|
||||||
|
Avg,
|
||||||
|
Paeth,
|
||||||
|
Adaptive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Filter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Filter::Adaptive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RowFilter> for Filter {
|
||||||
|
fn from(value: RowFilter) -> Self {
|
||||||
|
match value {
|
||||||
|
RowFilter::NoFilter => Filter::NoFilter,
|
||||||
|
RowFilter::Sub => Filter::Sub,
|
||||||
|
RowFilter::Up => Filter::Up,
|
||||||
|
RowFilter::Avg => Filter::Avg,
|
||||||
|
RowFilter::Paeth => Filter::Paeth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Filter {
|
||||||
|
pub(crate) fn from_simple(compression: Compression) -> Self {
|
||||||
|
match compression {
|
||||||
|
Compression::NoCompression => Filter::NoFilter, // with no DEFLATE filtering would only waste time
|
||||||
|
Compression::Fastest => Filter::Up, // pairs well with FdeflateUltraFast, producing much smaller files while being very fast
|
||||||
|
Compression::Fast => Filter::Adaptive,
|
||||||
|
Compression::Balanced => Filter::Adaptive,
|
||||||
|
Compression::High => Filter::Adaptive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unlike the public [Filter], does not include the "Adaptive" option
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum FilterType {
|
pub(crate) enum RowFilter {
|
||||||
NoFilter = 0,
|
NoFilter = 0,
|
||||||
Sub = 1,
|
Sub = 1,
|
||||||
Up = 2,
|
Up = 2,
|
||||||
@ -236,44 +280,33 @@ pub enum FilterType {
|
|||||||
Paeth = 4,
|
Paeth = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FilterType {
|
impl Default for RowFilter {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FilterType::Sub
|
RowFilter::Up
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterType {
|
impl RowFilter {
|
||||||
/// u8 -> Self. Temporary solution until Rust provides a canonical one.
|
pub fn from_u8(n: u8) -> Option<Self> {
|
||||||
pub fn from_u8(n: u8) -> Option<FilterType> {
|
|
||||||
match n {
|
match n {
|
||||||
0 => Some(FilterType::NoFilter),
|
0 => Some(Self::NoFilter),
|
||||||
1 => Some(FilterType::Sub),
|
1 => Some(Self::Sub),
|
||||||
2 => Some(FilterType::Up),
|
2 => Some(Self::Up),
|
||||||
3 => Some(FilterType::Avg),
|
3 => Some(Self::Avg),
|
||||||
4 => Some(FilterType::Paeth),
|
4 => Some(Self::Paeth),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Adaptive filtering tries every possible filter for each row and uses a heuristic to select the best one.
|
pub fn from_method(strat: Filter) -> Option<Self> {
|
||||||
/// This improves compression ratio, but makes encoding slightly slower.
|
match strat {
|
||||||
///
|
Filter::NoFilter => Some(Self::NoFilter),
|
||||||
/// It is recommended to use `Adaptive` whenever you care about compression ratio.
|
Filter::Sub => Some(Self::Sub),
|
||||||
/// Filtering is quite cheap compared to other parts of encoding, but can contribute
|
Filter::Up => Some(Self::Up),
|
||||||
/// to the compression ratio significantly.
|
Filter::Avg => Some(Self::Avg),
|
||||||
///
|
Filter::Paeth => Some(Self::Paeth),
|
||||||
/// `NonAdaptive` filtering is the default.
|
Filter::Adaptive => None,
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
}
|
||||||
#[repr(u8)]
|
|
||||||
pub enum AdaptiveFilterType {
|
|
||||||
Adaptive,
|
|
||||||
NonAdaptive,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for AdaptiveFilterType {
|
|
||||||
fn default() -> Self {
|
|
||||||
AdaptiveFilterType::NonAdaptive
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +346,7 @@ fn filter_paeth_stbi(a: u8, b: u8, c: u8) -> u8 {
|
|||||||
let hi = a.max(b);
|
let hi = a.max(b);
|
||||||
let t0 = if hi as i16 <= thresh { lo } else { c };
|
let t0 = if hi as i16 <= thresh { lo } else { c };
|
||||||
let t1 = if thresh <= lo as i16 { hi } else { t0 };
|
let t1 = if thresh <= lo as i16 { hi } else { t0 };
|
||||||
return t1;
|
t1
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, all(feature = "unstable", target_arch = "x86_64")))]
|
#[cfg(any(test, all(feature = "unstable", target_arch = "x86_64")))]
|
||||||
@ -370,12 +403,12 @@ fn filter_paeth_fpnge(a: u8, b: u8, c: u8) -> u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn unfilter(
|
pub(crate) fn unfilter(
|
||||||
mut filter: FilterType,
|
mut filter: RowFilter,
|
||||||
tbpp: BytesPerPixel,
|
tbpp: BytesPerPixel,
|
||||||
previous: &[u8],
|
previous: &[u8],
|
||||||
current: &mut [u8],
|
current: &mut [u8],
|
||||||
) {
|
) {
|
||||||
use self::FilterType::*;
|
use self::RowFilter::*;
|
||||||
|
|
||||||
// If the previous row is empty, then treat it as if it were filled with zeros.
|
// If the previous row is empty, then treat it as if it were filled with zeros.
|
||||||
if previous.is_empty() {
|
if previous.is_empty() {
|
||||||
@ -771,11 +804,9 @@ pub(crate) fn unfilter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BytesPerPixel::Four => {
|
BytesPerPixel::Four => {
|
||||||
#[cfg(all(feature = "unstable", target_arch = "x86_64"))]
|
// Using the `simd` module here has no effect on Linux
|
||||||
{
|
// and appears to regress performance on Windows, so we don't use it here.
|
||||||
simd::unfilter_paeth_u8::<4>(previous, current);
|
// See https://github.com/image-rs/image-png/issues/567
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut a_bpp = [0; 4];
|
let mut a_bpp = [0; 4];
|
||||||
let mut c_bpp = [0; 4];
|
let mut c_bpp = [0; 4];
|
||||||
@ -866,14 +897,14 @@ pub(crate) fn unfilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filter_internal(
|
fn filter_internal(
|
||||||
method: FilterType,
|
method: RowFilter,
|
||||||
bpp: usize,
|
bpp: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
previous: &[u8],
|
previous: &[u8],
|
||||||
current: &[u8],
|
current: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
) -> FilterType {
|
) -> RowFilter {
|
||||||
use self::FilterType::*;
|
use self::RowFilter::*;
|
||||||
|
|
||||||
// This value was chosen experimentally based on what achieved the best performance. The
|
// This value was chosen experimentally based on what achieved the best performance. The
|
||||||
// Rust compiler does auto-vectorization, and 32-bytes per loop iteration seems to enable
|
// Rust compiler does auto-vectorization, and 32-bytes per loop iteration seems to enable
|
||||||
@ -1005,24 +1036,20 @@ fn filter_internal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn filter(
|
pub(crate) fn filter(
|
||||||
method: FilterType,
|
method: Filter,
|
||||||
adaptive: AdaptiveFilterType,
|
|
||||||
bpp: BytesPerPixel,
|
bpp: BytesPerPixel,
|
||||||
previous: &[u8],
|
previous: &[u8],
|
||||||
current: &[u8],
|
current: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
) -> FilterType {
|
) -> RowFilter {
|
||||||
use FilterType::*;
|
use RowFilter::*;
|
||||||
let bpp = bpp.into_usize();
|
let bpp = bpp.into_usize();
|
||||||
let len = current.len();
|
let len = current.len();
|
||||||
|
|
||||||
match adaptive {
|
match method {
|
||||||
AdaptiveFilterType::NonAdaptive => {
|
Filter::Adaptive => {
|
||||||
filter_internal(method, bpp, len, previous, current, output)
|
|
||||||
}
|
|
||||||
AdaptiveFilterType::Adaptive => {
|
|
||||||
let mut min_sum: u64 = u64::MAX;
|
let mut min_sum: u64 = u64::MAX;
|
||||||
let mut filter_choice = FilterType::NoFilter;
|
let mut filter_choice = RowFilter::NoFilter;
|
||||||
for &filter in [Sub, Up, Avg, Paeth].iter() {
|
for &filter in [Sub, Up, Avg, Paeth].iter() {
|
||||||
filter_internal(filter, bpp, len, previous, current, output);
|
filter_internal(filter, bpp, len, previous, current, output);
|
||||||
let sum = sum_buffer(output);
|
let sum = sum_buffer(output);
|
||||||
@ -1037,6 +1064,10 @@ pub(crate) fn filter(
|
|||||||
}
|
}
|
||||||
filter_choice
|
filter_choice
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
let filter = RowFilter::from_method(method).unwrap();
|
||||||
|
filter_internal(filter, bpp, len, previous, current, output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,11 +1107,10 @@ mod test {
|
|||||||
let previous: Vec<_> = iter::repeat(1).take(LEN.into()).collect();
|
let previous: Vec<_> = iter::repeat(1).take(LEN.into()).collect();
|
||||||
let current: Vec<_> = (0..LEN).collect();
|
let current: Vec<_> = (0..LEN).collect();
|
||||||
let expected = current.clone();
|
let expected = current.clone();
|
||||||
let adaptive = AdaptiveFilterType::NonAdaptive;
|
|
||||||
|
|
||||||
let roundtrip = |kind, bpp: BytesPerPixel| {
|
let roundtrip = |kind: RowFilter, bpp: BytesPerPixel| {
|
||||||
let mut output = vec![0; LEN.into()];
|
let mut output = vec![0; LEN.into()];
|
||||||
filter(kind, adaptive, bpp, &previous, ¤t, &mut output);
|
filter(kind.into(), bpp, &previous, ¤t, &mut output);
|
||||||
unfilter(kind, bpp, &previous, &mut output);
|
unfilter(kind, bpp, &previous, &mut output);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
output, expected,
|
output, expected,
|
||||||
@ -1090,11 +1120,11 @@ mod test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let filters = [
|
let filters = [
|
||||||
FilterType::NoFilter,
|
RowFilter::NoFilter,
|
||||||
FilterType::Sub,
|
RowFilter::Sub,
|
||||||
FilterType::Up,
|
RowFilter::Up,
|
||||||
FilterType::Avg,
|
RowFilter::Avg,
|
||||||
FilterType::Paeth,
|
RowFilter::Paeth,
|
||||||
];
|
];
|
||||||
|
|
||||||
let bpps = [
|
let bpps = [
|
||||||
@ -1139,11 +1169,10 @@ mod test {
|
|||||||
let previous: Vec<_> = (0..LEN).collect();
|
let previous: Vec<_> = (0..LEN).collect();
|
||||||
let current: Vec<_> = (0..LEN).collect();
|
let current: Vec<_> = (0..LEN).collect();
|
||||||
let expected = current.clone();
|
let expected = current.clone();
|
||||||
let adaptive = AdaptiveFilterType::NonAdaptive;
|
|
||||||
|
|
||||||
let roundtrip = |kind, bpp: BytesPerPixel| {
|
let roundtrip = |kind: RowFilter, bpp: BytesPerPixel| {
|
||||||
let mut output = vec![0; LEN.into()];
|
let mut output = vec![0; LEN.into()];
|
||||||
filter(kind, adaptive, bpp, &previous, ¤t, &mut output);
|
filter(kind.into(), bpp, &previous, ¤t, &mut output);
|
||||||
unfilter(kind, bpp, &previous, &mut output);
|
unfilter(kind, bpp, &previous, &mut output);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
output, expected,
|
output, expected,
|
||||||
@ -1153,11 +1182,11 @@ mod test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let filters = [
|
let filters = [
|
||||||
FilterType::NoFilter,
|
RowFilter::NoFilter,
|
||||||
FilterType::Sub,
|
RowFilter::Sub,
|
||||||
FilterType::Up,
|
RowFilter::Up,
|
||||||
FilterType::Avg,
|
RowFilter::Avg,
|
||||||
FilterType::Paeth,
|
RowFilter::Paeth,
|
||||||
];
|
];
|
||||||
|
|
||||||
let bpps = [
|
let bpps = [
|
@ -12,9 +12,10 @@
|
|||||||
//! ### Using the decoder
|
//! ### Using the decoder
|
||||||
//! ```
|
//! ```
|
||||||
//! use std::fs::File;
|
//! use std::fs::File;
|
||||||
|
//! use std::io::BufReader;
|
||||||
//! // The decoder is a build for reader and can be used to set various decoding options
|
//! // The decoder is a build for reader and can be used to set various decoding options
|
||||||
//! // via `Transformations`. The default output transformation is `Transformations::IDENTITY`.
|
//! // via `Transformations`. The default output transformation is `Transformations::IDENTITY`.
|
||||||
//! let decoder = png::Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap());
|
//! let decoder = png::Decoder::new(BufReader::new(File::open("tests/pngsuite/basi0g01.png").unwrap()));
|
||||||
//! let mut reader = decoder.read_info().unwrap();
|
//! let mut reader = decoder.read_info().unwrap();
|
||||||
//! // Allocate the output buffer.
|
//! // Allocate the output buffer.
|
||||||
//! let mut buf = vec![0; reader.output_buffer_size()];
|
//! let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
@ -77,7 +78,7 @@ pub use crate::common::*;
|
|||||||
pub use crate::decoder::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder};
|
pub use crate::decoder::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder};
|
||||||
pub use crate::decoder::{Decoder, InterlaceInfo, InterlacedRow, Limits, OutputInfo, Reader};
|
pub use crate::decoder::{Decoder, InterlaceInfo, InterlacedRow, Limits, OutputInfo, Reader};
|
||||||
pub use crate::encoder::{Encoder, EncodingError, StreamWriter, Writer};
|
pub use crate::encoder::{Encoder, EncodingError, StreamWriter, Writer};
|
||||||
pub use crate::filter::{AdaptiveFilterType, FilterType};
|
pub use crate::filter::Filter;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod test_utils;
|
pub(crate) mod test_utils;
|
@ -5,9 +5,9 @@
|
|||||||
//! chunks. There are three kinds of text chunks.
|
//! chunks. There are three kinds of text chunks.
|
||||||
//! - `tEXt`: This has a `keyword` and `text` field, and is ISO 8859-1 encoded.
|
//! - `tEXt`: This has a `keyword` and `text` field, and is ISO 8859-1 encoded.
|
||||||
//! - `zTXt`: This is semantically the same as `tEXt`, i.e. it has the same fields and
|
//! - `zTXt`: This is semantically the same as `tEXt`, i.e. it has the same fields and
|
||||||
//! encoding, but the `text` field is compressed before being written into the PNG file.
|
//! encoding, but the `text` field is compressed before being written into the PNG file.
|
||||||
//! - `iTXt`: This chunk allows for its `text` field to be any valid UTF-8, and supports
|
//! - `iTXt`: This chunk allows for its `text` field to be any valid UTF-8, and supports
|
||||||
//! compression of the text field as well.
|
//! compression of the text field as well.
|
||||||
//!
|
//!
|
||||||
//! The `ISO 8859-1` encoding technically doesn't allow any control characters
|
//! The `ISO 8859-1` encoding technically doesn't allow any control characters
|
||||||
//! to be used, but in practice these values are encountered anyway. This can
|
//! to be used, but in practice these values are encountered anyway. This can
|
||||||
@ -24,17 +24,13 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use std::fs::File;
|
//! use std::fs::File;
|
||||||
|
//! use std::io::BufReader;
|
||||||
//! use std::iter::FromIterator;
|
//! use std::iter::FromIterator;
|
||||||
//! use std::path::PathBuf;
|
//! use std::path::PathBuf;
|
||||||
//!
|
//!
|
||||||
//! // Opening a png file that has a zTXt chunk
|
//! // Opening a png file that has a zTXt chunk
|
||||||
//! let decoder = png::Decoder::new(
|
//! let decoder = png::Decoder::new(
|
||||||
//! File::open(PathBuf::from_iter([
|
//! BufReader::new(File::open("tests/text_chunk_examples/ztxt_example.png").unwrap())
|
||||||
//! "tests",
|
|
||||||
//! "text_chunk_examples",
|
|
||||||
//! "ztxt_example.png",
|
|
||||||
//! ]))
|
|
||||||
//! .unwrap(),
|
|
||||||
//! );
|
//! );
|
||||||
//! let mut reader = decoder.read_info().unwrap();
|
//! let mut reader = decoder.read_info().unwrap();
|
||||||
//! // If the text chunk is before the image data frames, `reader.info()` already contains the text.
|
//! // If the text chunk is before the image data frames, `reader.info()` already contains the text.
|
69
third_party/rust/png/v0_17/BUILD.gn
vendored
69
third_party/rust/png/v0_17/BUILD.gn
vendored
@ -1,69 +0,0 @@
|
|||||||
# Copyright 2023 The Chromium Authors
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by
|
|
||||||
# tools/crates/gnrt.
|
|
||||||
# Do not edit!
|
|
||||||
|
|
||||||
import("//build/rust/cargo_crate.gni")
|
|
||||||
|
|
||||||
cargo_crate("lib") {
|
|
||||||
crate_name = "png"
|
|
||||||
epoch = "0.17"
|
|
||||||
crate_type = "rlib"
|
|
||||||
crate_root =
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/lib.rs"
|
|
||||||
sources = [
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/adam7.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/benchable_apis.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/chunk.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/common.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/interlace_info.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/mod.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/read_decoder.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/stream.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/transform.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/transform/palette.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/unfiltering_buffer.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/decoder/zlib.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/encoder.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/filter.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/lib.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/srgb.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/test_utils.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/text_metadata.rs",
|
|
||||||
"//third_party/rust/chromium_crates_io/vendor/png-0.17.16/src/traits.rs",
|
|
||||||
]
|
|
||||||
inputs = []
|
|
||||||
|
|
||||||
build_native_rust_unit_tests = false
|
|
||||||
edition = "2018"
|
|
||||||
cargo_pkg_version = "0.17.16"
|
|
||||||
cargo_pkg_authors = "The image-rs Developers"
|
|
||||||
cargo_pkg_name = "png"
|
|
||||||
cargo_pkg_description = "PNG decoding and encoding library in pure Rust"
|
|
||||||
library_configs -= [ "//build/config/coverage:default_coverage" ]
|
|
||||||
library_configs -= [ "//build/config/compiler:chromium_code" ]
|
|
||||||
library_configs += [ "//build/config/compiler:no_chromium_code" ]
|
|
||||||
executable_configs -= [ "//build/config/compiler:chromium_code" ]
|
|
||||||
executable_configs += [ "//build/config/compiler:no_chromium_code" ]
|
|
||||||
proc_macro_configs -= [ "//build/config/compiler:chromium_code" ]
|
|
||||||
proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ]
|
|
||||||
deps = [
|
|
||||||
"//third_party/rust/bitflags/v1:lib",
|
|
||||||
"//third_party/rust/crc32fast/v1:lib",
|
|
||||||
"//third_party/rust/fdeflate/v0_3:lib",
|
|
||||||
"//third_party/rust/flate2/v1:lib",
|
|
||||||
"//third_party/rust/miniz_oxide/v0_8:lib",
|
|
||||||
]
|
|
||||||
library_configs -= [ "//build/config/compiler:default_optimization" ]
|
|
||||||
executable_configs -= [ "//build/config/compiler:default_optimization" ]
|
|
||||||
proc_macro_configs -= [ "//build/config/compiler:default_optimization" ]
|
|
||||||
library_configs += [ "//build/config/compiler:optimize" ]
|
|
||||||
executable_configs += [ "//build/config/compiler:optimize" ]
|
|
||||||
proc_macro_configs += [ "//build/config/compiler:optimize" ]
|
|
||||||
rustflags = [
|
|
||||||
"--cap-lints=allow", # Suppress all warnings in crates.io crates
|
|
||||||
]
|
|
||||||
}
|
|
69
third_party/rust/png/v0_18/BUILD.gn
vendored
Normal file
69
third_party/rust/png/v0_18/BUILD.gn
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Copyright 2023 The Chromium Authors
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by
|
||||||
|
# tools/crates/gnrt.
|
||||||
|
# Do not edit!
|
||||||
|
|
||||||
|
import("//build/rust/cargo_crate.gni")
|
||||||
|
|
||||||
|
cargo_crate("lib") {
|
||||||
|
crate_name = "png"
|
||||||
|
epoch = "0.18"
|
||||||
|
crate_type = "rlib"
|
||||||
|
crate_root =
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/lib.rs"
|
||||||
|
sources = [
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/adam7.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/benchable_apis.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/chunk.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/common.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/interlace_info.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/mod.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/read_decoder.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/stream.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/transform.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/transform/palette.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/unfiltering_buffer.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/decoder/zlib.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/encoder.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/filter.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/lib.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/srgb.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/test_utils.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/text_metadata.rs",
|
||||||
|
"//third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/src/traits.rs",
|
||||||
|
]
|
||||||
|
inputs = []
|
||||||
|
|
||||||
|
build_native_rust_unit_tests = false
|
||||||
|
edition = "2021"
|
||||||
|
cargo_pkg_version = "0.18.0-rc"
|
||||||
|
cargo_pkg_authors = "The image-rs Developers"
|
||||||
|
cargo_pkg_name = "png"
|
||||||
|
cargo_pkg_description = "PNG decoding and encoding library in pure Rust"
|
||||||
|
library_configs -= [ "//build/config/coverage:default_coverage" ]
|
||||||
|
library_configs -= [ "//build/config/compiler:chromium_code" ]
|
||||||
|
library_configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||||
|
executable_configs -= [ "//build/config/compiler:chromium_code" ]
|
||||||
|
executable_configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||||
|
proc_macro_configs -= [ "//build/config/compiler:chromium_code" ]
|
||||||
|
proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||||
|
deps = [
|
||||||
|
"//third_party/rust/bitflags/v2:lib",
|
||||||
|
"//third_party/rust/crc32fast/v1:lib",
|
||||||
|
"//third_party/rust/fdeflate/v0_3:lib",
|
||||||
|
"//third_party/rust/flate2/v1:lib",
|
||||||
|
"//third_party/rust/miniz_oxide/v0_8:lib",
|
||||||
|
]
|
||||||
|
library_configs -= [ "//build/config/compiler:default_optimization" ]
|
||||||
|
executable_configs -= [ "//build/config/compiler:default_optimization" ]
|
||||||
|
proc_macro_configs -= [ "//build/config/compiler:default_optimization" ]
|
||||||
|
library_configs += [ "//build/config/compiler:optimize" ]
|
||||||
|
executable_configs += [ "//build/config/compiler:optimize" ]
|
||||||
|
proc_macro_configs += [ "//build/config/compiler:optimize" ]
|
||||||
|
rustflags = [
|
||||||
|
"--cap-lints=allow", # Suppress all warnings in crates.io crates
|
||||||
|
]
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
Name: png
|
Name: png
|
||||||
URL: https://crates.io/crates/png
|
URL: https://crates.io/crates/png
|
||||||
Version: 0.17.16
|
Version: 0.18.0-rc
|
||||||
Revision: fbf256669ff23594bf4c618b61fde6a52b79e088
|
Revision: eb9b5d7f371b88f15aaca6a8d21c58b86c400d76
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
License File: //third_party/rust/chromium_crates_io/vendor/png-0.17.16/LICENSE-APACHE
|
License File: //third_party/rust/chromium_crates_io/vendor/png-0.18.0-rc/LICENSE-APACHE
|
||||||
Shipped: yes
|
Shipped: yes
|
||||||
Security Critical: yes
|
Security Critical: yes
|
||||||
|
|
Reference in New Issue
Block a user