[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
|
||||
cxx_bindings = skia_codec_rust_png_ffi_cxx_bridge_srcs
|
||||
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 += [
|
||||
":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"
|
||||
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]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
@ -115,7 +110,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags",
|
||||
"bstr",
|
||||
"bytemuck",
|
||||
"bytes",
|
||||
@ -954,10 +949,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.16"
|
||||
version = "0.18.0-rc"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
|
@ -30,7 +30,7 @@ itertools = "0.11"
|
||||
lazy_static = "1"
|
||||
libc = "0.2"
|
||||
nom = "7.1.3"
|
||||
png = "0.17"
|
||||
png = "=0.18.0-rc"
|
||||
proc-macro2 = "1"
|
||||
prost = "0.13.3"
|
||||
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"]
|
||||
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]]
|
||||
who = "Manish Goregaokar <manishearth@google.com>"
|
||||
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"]
|
||||
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"]
|
||||
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"]
|
||||
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"]
|
||||
|
||||
[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
|
||||
|
||||
### Added
|
||||
@ -7,7 +34,7 @@
|
||||
* Add support for parsing the sBIT chunk ([#524])
|
||||
* Add support for parsing the bKGD chunk ([#538])
|
||||
* 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
|
||||
|
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.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.57"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
name = "png"
|
||||
version = "0.17.16"
|
||||
version = "0.18.0-rc"
|
||||
authors = ["The image-rs Developers"]
|
||||
build = false
|
||||
include = [
|
||||
@ -56,10 +56,6 @@ path = "examples/png-generate.rs"
|
||||
name = "pngcheck"
|
||||
path = "examples/pngcheck.rs"
|
||||
|
||||
[[example]]
|
||||
name = "show"
|
||||
path = "examples/show.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "decoder"
|
||||
path = "benches/decoder.rs"
|
||||
@ -78,7 +74,7 @@ harness = false
|
||||
required-features = ["benchmarks"]
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "1.0"
|
||||
version = "2.0"
|
||||
|
||||
[dependencies.crc32fast]
|
||||
version = "1.2.0"
|
||||
@ -87,7 +83,7 @@ version = "1.2.0"
|
||||
version = "0.3.3"
|
||||
|
||||
[dependencies.flate2]
|
||||
version = "1.0.11"
|
||||
version = "1.0.35"
|
||||
|
||||
[dependencies.miniz_oxide]
|
||||
version = "0.8"
|
||||
@ -109,11 +105,6 @@ version = "0.4.0"
|
||||
[dev-dependencies.getopts]
|
||||
version = "0.2.14"
|
||||
|
||||
[dev-dependencies.glium]
|
||||
version = "0.32"
|
||||
features = ["glutin"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.glob]
|
||||
version = "0.3"
|
||||
|
||||
@ -126,6 +117,7 @@ version = "1.0.1"
|
||||
[features]
|
||||
benchmarks = []
|
||||
unstable = ["crc32fast/nightly"]
|
||||
zlib-rs = ["flate2/zlib-rs"]
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
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]
|
||||
name = "png"
|
||||
version = "0.17.16"
|
||||
version = "0.18.0-rc"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
description = "PNG decoding and encoding library in pure Rust"
|
||||
@ -8,8 +8,8 @@ categories = ["multimedia::images"]
|
||||
authors = ["The image-rs Developers"]
|
||||
repository = "https://github.com/image-rs/image-png"
|
||||
|
||||
edition = "2018"
|
||||
rust-version = "1.57"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
include = [
|
||||
"/LICENSE-MIT",
|
||||
"/LICENSE-APACHE",
|
||||
@ -21,10 +21,10 @@ include = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
bitflags = "2.0"
|
||||
crc32fast = "1.2.0"
|
||||
fdeflate = "0.3.3"
|
||||
flate2 = "1.0.11"
|
||||
flate2 = "1.0.35"
|
||||
miniz_oxide = { version = "0.8", features = ["simd"] }
|
||||
|
||||
[dev-dependencies]
|
||||
@ -33,13 +33,19 @@ byteorder = "1.5.0"
|
||||
clap = { version = "3.0", features = ["derive"] }
|
||||
criterion = "0.4.0"
|
||||
getopts = "0.2.14"
|
||||
glium = { version = "0.32", features = ["glutin"], default-features = false }
|
||||
glob = "0.3"
|
||||
rand = "0.8.4"
|
||||
term = "1.0.1"
|
||||
|
||||
[features]
|
||||
# Use nightly-only features for a minor performance boost in PNG decoding
|
||||
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 = []
|
||||
|
||||
[lints.rust]
|
@ -1,4 +1,4 @@
|
||||
use std::fs;
|
||||
use std::{fs, io::Cursor};
|
||||
|
||||
use criterion::{
|
||||
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, 12288, 0x7fffffff); // 576 MB
|
||||
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}
|
||||
@ -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"));
|
||||
}
|
||||
|
||||
/// This benchmarks decoding via a call to `Reader::next_frame`.
|
||||
fn bench_file(g: &mut BenchmarkGroup<WallTime>, data: Vec<u8>, name: String) {
|
||||
if data.len() > 1_000_000 {
|
||||
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 image = vec![0; reader.output_buffer_size()];
|
||||
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 png::benchable_apis::unfilter;
|
||||
use png::FilterType;
|
||||
use png::Filter;
|
||||
use rand::Rng;
|
||||
|
||||
fn unfilter_all(c: &mut Criterion) {
|
||||
let bpps = [1, 2, 3, 4, 6, 8];
|
||||
let filters = [
|
||||
FilterType::Sub,
|
||||
FilterType::Up,
|
||||
FilterType::Avg,
|
||||
FilterType::Paeth,
|
||||
];
|
||||
let filters = [Filter::Sub, Filter::Up, Filter::Avg, Filter::Paeth];
|
||||
for &filter in filters.iter() {
|
||||
for &bpp in bpps.iter() {
|
||||
bench_unfilter(c, filter, bpp);
|
||||
@ -30,7 +25,7 @@ fn unfilter_all(c: &mut Criterion) {
|
||||
criterion_group!(benches, unfilter_all);
|
||||
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");
|
||||
|
||||
fn get_random_bytes<R: Rng>(rng: &mut R, n: usize) -> Vec<u8> {
|
@ -1,7 +1,7 @@
|
||||
/// Tests "editing"/re-encoding of an image:
|
||||
/// decoding, editing, re-encoding
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
use std::io::{BufReader, BufWriter};
|
||||
use std::path::Path;
|
||||
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");
|
||||
// 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`.
|
||||
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()?;
|
||||
// Allocate the output buffer.
|
||||
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 png::Decoder;
|
||||
@ -43,20 +43,16 @@ fn run_encode(
|
||||
encoder.set_depth(bit_depth);
|
||||
encoder.set_compression(match args.speed {
|
||||
Speed::Fast => png::Compression::Fast,
|
||||
Speed::Default => png::Compression::Default,
|
||||
Speed::Best => png::Compression::Best,
|
||||
Speed::Default => png::Compression::Balanced,
|
||||
Speed::Best => png::Compression::High,
|
||||
});
|
||||
encoder.set_filter(match args.filter {
|
||||
Filter::None => png::FilterType::NoFilter,
|
||||
Filter::Sub => png::FilterType::Sub,
|
||||
Filter::Up => png::FilterType::Up,
|
||||
Filter::Average => png::FilterType::Avg,
|
||||
Filter::Paeth => png::FilterType::Paeth,
|
||||
Filter::Adaptive => png::FilterType::Paeth,
|
||||
});
|
||||
encoder.set_adaptive_filter(match args.filter {
|
||||
Filter::Adaptive => png::AdaptiveFilterType::Adaptive,
|
||||
_ => png::AdaptiveFilterType::NonAdaptive,
|
||||
Filter::None => png::Filter::NoFilter,
|
||||
Filter::Sub => png::Filter::Sub,
|
||||
Filter::Up => png::Filter::Up,
|
||||
Filter::Average => png::Filter::Avg,
|
||||
Filter::Paeth => png::Filter::Paeth,
|
||||
Filter::Adaptive => png::Filter::Adaptive,
|
||||
});
|
||||
let mut encoder = encoder.write_header().unwrap();
|
||||
encoder.write_image_data(image).unwrap();
|
||||
@ -66,7 +62,7 @@ fn run_encode(
|
||||
|
||||
#[inline(never)]
|
||||
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();
|
||||
}
|
||||
|
||||
@ -111,7 +107,7 @@ fn main() {
|
||||
|
||||
// Parse
|
||||
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)
|
||||
== Some(png::ColorType::Indexed)
|
||||
{
|
@ -2,12 +2,13 @@
|
||||
//! This module is gated behind the "benchmarks" feature.
|
||||
|
||||
use crate::common::BytesPerPixel;
|
||||
use crate::filter::FilterType;
|
||||
use crate::filter::{Filter, RowFilter};
|
||||
use crate::{BitDepth, ColorType, Info};
|
||||
|
||||
/// Re-exporting `unfilter` to make it easier to benchmark, despite some items being only
|
||||
/// `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);
|
||||
crate::filter::unfilter(filter, tbpp, previous, current)
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
//! 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 io::Write;
|
||||
use std::{borrow::Cow, convert::TryFrom, fmt, io};
|
||||
@ -77,6 +79,16 @@ impl ColorType {
|
||||
|| self == ColorType::Rgba))
|
||||
|| (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.
|
||||
@ -303,33 +315,104 @@ impl AnimationControl {
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
#[non_exhaustive]
|
||||
pub enum Compression {
|
||||
/// Default level
|
||||
Default,
|
||||
/// Fast minimal compression
|
||||
Fast,
|
||||
/// Higher compression level
|
||||
/// No compression whatsoever. Fastest, but results in large files.
|
||||
NoCompression,
|
||||
/// Extremely fast but light compression.
|
||||
Fastest,
|
||||
/// Extremely fast compression with a decent compression ratio.
|
||||
///
|
||||
/// Best in this context isn't actually the highest possible level
|
||||
/// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
|
||||
/// library.
|
||||
Best,
|
||||
#[deprecated(
|
||||
since = "0.17.6",
|
||||
note = "use one of the other compression levels instead, such as 'fast'"
|
||||
)]
|
||||
Huffman,
|
||||
#[deprecated(
|
||||
since = "0.17.6",
|
||||
note = "use one of the other compression levels instead, such as 'fast'"
|
||||
)]
|
||||
Rle,
|
||||
/// Significantly outperforms libpng and other popular encoders
|
||||
/// by using a [specialized DEFLATE implementation tuned for PNG](https://crates.io/crates/fdeflate),
|
||||
/// while still providing better compression ratio than the fastest modes of other encoders.
|
||||
Fast,
|
||||
/// Balances encoding speed and compression ratio
|
||||
Balanced,
|
||||
/// Spend more time to produce a slightly smaller file than with `Default`
|
||||
High,
|
||||
}
|
||||
|
||||
impl Default for Compression {
|
||||
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 animation_control: Option<AnimationControl>,
|
||||
pub compression: Compression,
|
||||
/// Gamma of the source system.
|
||||
/// Set by both `gAMA` as well as to a replacement by `sRGB` chunk.
|
||||
pub source_gamma: Option<ScaledFloat>,
|
||||
@ -633,9 +715,6 @@ impl Default for Info<'_> {
|
||||
pixel_dims: None,
|
||||
frame_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_chromaticities: None,
|
||||
srgb: None,
|
||||
@ -683,14 +762,14 @@ impl Info<'_> {
|
||||
|
||||
/// Returns the number of bits per pixel.
|
||||
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.
|
||||
pub fn bytes_per_pixel(&self) -> 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.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.
|
||||
@ -725,6 +804,24 @@ impl Info<'_> {
|
||||
.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.
|
||||
///
|
||||
/// Any ICC profiles will be ignored.
|
||||
@ -735,91 +832,6 @@ impl Info<'_> {
|
||||
self.srgb = Some(rendering_intent);
|
||||
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 {
|
||||
@ -876,6 +888,7 @@ bitflags::bitflags! {
|
||||
const SCALE_16 = 0x8000; // read only
|
||||
```
|
||||
"]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Transformations: u32 {
|
||||
/// No transformation
|
||||
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::unfiltering_buffer::UnfilteringBuffer;
|
||||
|
||||
use std::io::Read;
|
||||
use std::io::{BufRead, Seek};
|
||||
use std::mem;
|
||||
|
||||
use crate::adam7::{self, Adam7Info};
|
||||
@ -86,7 +86,7 @@ impl Default for Limits {
|
||||
}
|
||||
|
||||
/// PNG Decoder
|
||||
pub struct Decoder<R: Read> {
|
||||
pub struct Decoder<R: BufRead + Seek> {
|
||||
read_decoder: ReadDecoder<R>,
|
||||
/// Output 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.
|
||||
pub fn new(r: R) -> Decoder<R> {
|
||||
Decoder::new_with_limits(r, Limits::default())
|
||||
@ -159,17 +159,18 @@ impl<R: Read> Decoder<R> {
|
||||
///
|
||||
/// ```
|
||||
/// use std::fs::File;
|
||||
/// use std::io::BufReader;
|
||||
/// use png::{Decoder, Limits};
|
||||
/// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes.
|
||||
/// let mut limits = Limits::default();
|
||||
/// 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());
|
||||
///
|
||||
/// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
|
||||
/// let mut limits = Limits::default();
|
||||
/// 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());
|
||||
/// ```
|
||||
pub fn set_limits(&mut self, limits: Limits) {
|
||||
@ -248,8 +249,9 @@ impl<R: Read> Decoder<R> {
|
||||
/// eg.
|
||||
/// ```
|
||||
/// use std::fs::File;
|
||||
/// use std::io::BufReader;
|
||||
/// 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);
|
||||
/// assert!(decoder.read_info().is_ok());
|
||||
/// ```
|
||||
@ -262,8 +264,9 @@ impl<R: Read> Decoder<R> {
|
||||
/// eg.
|
||||
/// ```
|
||||
/// use std::fs::File;
|
||||
/// use std::io::BufReader;
|
||||
/// 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);
|
||||
/// assert!(decoder.read_info().is_ok());
|
||||
/// ```
|
||||
@ -281,7 +284,7 @@ impl<R: Read> Decoder<R> {
|
||||
/// PNG reader (mostly high-level interface)
|
||||
///
|
||||
/// 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>,
|
||||
bpp: BytesPerPixel,
|
||||
subframe: SubframeInfo,
|
||||
@ -317,7 +320,7 @@ struct SubframeInfo {
|
||||
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
|
||||
/// returns a reference to the `FrameControl` info that describes it.
|
||||
/// Skips and discards the image data of the previous frame if necessary.
|
||||
@ -474,14 +477,45 @@ impl<R: Read> Reader<R> {
|
||||
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> {
|
||||
self.next_interlaced_row()
|
||||
.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> {
|
||||
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() {
|
||||
None => {
|
||||
self.finish_decoding()?;
|
||||
@ -498,24 +532,21 @@ impl<R: Read> Reader<R> {
|
||||
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 {
|
||||
InterlaceInfo::Adam7(Adam7Info { width, .. }) => width,
|
||||
InterlaceInfo::Adam7(Adam7Info { width, .. }) => *width,
|
||||
InterlaceInfo::Null(_) => self.subframe.width,
|
||||
};
|
||||
let output_line_size = 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,
|
||||
}))
|
||||
self.output_line_size(width)
|
||||
}
|
||||
|
||||
/// Read the rest of the image and chunks and finish up, including text chunks or others
|
@ -1,9 +1,7 @@
|
||||
use super::stream::{
|
||||
DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder, CHUNK_BUFFER_SIZE,
|
||||
};
|
||||
use super::stream::{DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder};
|
||||
use super::Limits;
|
||||
|
||||
use std::io::{BufRead, BufReader, ErrorKind, Read};
|
||||
use std::io::{BufRead, ErrorKind, Read, Seek};
|
||||
|
||||
use crate::chunk;
|
||||
use crate::common::Info;
|
||||
@ -18,14 +16,14 @@ use crate::common::Info;
|
||||
/// * `finish_decoding_image_data()` - discarding remaining data from `IDAT` / `fdAT` sequence
|
||||
/// * `read_until_end_of_input()` - reading until `IEND` chunk
|
||||
pub(crate) struct ReadDecoder<R: Read> {
|
||||
reader: BufReader<R>,
|
||||
reader: R,
|
||||
decoder: StreamingDecoder,
|
||||
}
|
||||
|
||||
impl<R: Read> ReadDecoder<R> {
|
||||
impl<R: BufRead + Seek> ReadDecoder<R> {
|
||||
pub fn new(r: R) -> Self {
|
||||
Self {
|
||||
reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
|
||||
reader: r,
|
||||
decoder: StreamingDecoder::new(),
|
||||
}
|
||||
}
|
||||
@ -34,10 +32,7 @@ impl<R: Read> ReadDecoder<R> {
|
||||
let mut decoder = StreamingDecoder::new_with_options(options);
|
||||
decoder.limits = Limits::default();
|
||||
|
||||
Self {
|
||||
reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
|
||||
decoder,
|
||||
}
|
||||
Self { reader: r, decoder }
|
||||
}
|
||||
|
||||
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
|
||||
/// be used to detect that build.
|
||||
#[allow(unexpected_cfgs)]
|
||||
const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
|
||||
|
||||
/// 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> {
|
||||
let mut parse = || {
|
||||
let info = self.info.as_mut().unwrap();
|
||||
if info.palette.is_some() {
|
||||
let info = self.info.as_mut().unwrap();
|
||||
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(
|
||||
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,
|
||||
FormatErrorInner::InvalidSbit {
|
||||
sample_depth,
|
||||
sbit: *sbit,
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
|
||||
for sbit in &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();
|
||||
}
|
||||
info.sbit = Some(Cow::Owned(vec));
|
||||
Ok(Decoded::Nothing)
|
||||
}
|
||||
|
||||
@ -1345,11 +1341,6 @@ impl StreamingDecoder {
|
||||
};
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -1370,11 +1361,6 @@ impl StreamingDecoder {
|
||||
let source_gamma = ScaledFloat::from_scaled(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)
|
||||
}
|
||||
}
|
||||
@ -1398,8 +1384,6 @@ impl StreamingDecoder {
|
||||
|
||||
// Set srgb and override source gamma and chromaticities.
|
||||
info.srgb = Some(rendering_intent);
|
||||
info.source_gamma = Some(crate::srgb::substitute_gamma());
|
||||
info.source_chromaticities = Some(crate::srgb::substitute_chromaticities());
|
||||
Ok(Decoded::Nothing)
|
||||
}
|
||||
}
|
||||
@ -1871,22 +1855,25 @@ mod tests {
|
||||
use super::ScaledFloat;
|
||||
use super::SourceChromaticities;
|
||||
use crate::test_utils::*;
|
||||
use crate::{Decoder, DecodingError, Reader};
|
||||
use crate::{Decoder, DecodingError, Reader, SrgbRenderingIntent, Unit};
|
||||
use approx::assert_relative_eq;
|
||||
use byteorder::WriteBytesExt;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
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;
|
||||
|
||||
#[test]
|
||||
fn image_gamma() -> Result<(), ()> {
|
||||
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 actual: Option<ScaledFloat> = reader.info().source_gamma;
|
||||
let actual: Option<ScaledFloat> = reader.info().gamma();
|
||||
assert!(actual == expected);
|
||||
}
|
||||
trial("tests/pngsuite/f00n0g08.png", None);
|
||||
@ -1925,9 +1912,9 @@ mod tests {
|
||||
#[test]
|
||||
fn image_source_chromaticities() -> Result<(), ()> {
|
||||
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 actual: Option<SourceChromaticities> = reader.info().source_chromaticities;
|
||||
let actual: Option<SourceChromaticities> = reader.info().chromaticities();
|
||||
assert!(actual == expected);
|
||||
}
|
||||
trial(
|
||||
@ -2112,7 +2099,7 @@ mod tests {
|
||||
#[test]
|
||||
fn image_source_sbit() {
|
||||
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 actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
|
||||
assert!(actual == expected);
|
||||
@ -2139,7 +2126,9 @@ mod tests {
|
||||
// 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
|
||||
// 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 icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
|
||||
|
||||
@ -2162,24 +2151,67 @@ mod tests {
|
||||
enc.write_image_data(&[0]).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();
|
||||
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]
|
||||
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());
|
||||
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);
|
||||
assert!(decoder.read_info().is_ok());
|
||||
}
|
||||
|
||||
/// Test handling of `mDCV` and `cLLI` chunks.
|
||||
/// Test handling of `cICP`, `mDCV`, and `cLLI` chunks.
|
||||
#[test]
|
||||
fn test_mdcv_and_clli_chunks() {
|
||||
let decoder = crate::Decoder::new(File::open("tests/bugfixes/cicp_pq.png").unwrap());
|
||||
fn test_cicp_mdcv_and_clli_chunks() {
|
||||
let decoder = crate::Decoder::new(BufReader::new(
|
||||
File::open("tests/bugfixes/cicp_pq.png").unwrap(),
|
||||
));
|
||||
let reader = decoder.read_info().unwrap();
|
||||
let info = reader.info();
|
||||
|
||||
@ -2209,8 +2241,9 @@ mod tests {
|
||||
/// 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 decoder = crate::Decoder::new(BufReader::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();
|
||||
@ -2222,7 +2255,7 @@ mod tests {
|
||||
fn test_finishing_twice() {
|
||||
let mut png = Vec::new();
|
||||
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();
|
||||
|
||||
// First call to `finish` - expecting success.
|
||||
@ -2310,7 +2343,7 @@ mod tests {
|
||||
write_fdat_prefix(&mut png, 2, 8);
|
||||
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 buf = vec![0; reader.output_buffer_size()];
|
||||
reader.next_frame(&mut buf).unwrap();
|
||||
@ -2338,7 +2371,7 @@ mod tests {
|
||||
write_fdat_prefix(&mut png, 2, 8);
|
||||
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 buf = vec![0; reader.output_buffer_size()];
|
||||
reader.next_frame(&mut buf).unwrap();
|
||||
@ -2376,7 +2409,7 @@ mod tests {
|
||||
};
|
||||
|
||||
// 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 buf = vec![0; reader.output_buffer_size()];
|
||||
let Some(animation_control) = reader.info().animation_control else {
|
||||
@ -2439,7 +2472,7 @@ mod tests {
|
||||
write_iend(&mut 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 buf = vec![0; reader.output_buffer_size()];
|
||||
|
||||
@ -2457,7 +2490,7 @@ mod tests {
|
||||
write_chunk(&mut png, b"IDAT", &[]);
|
||||
png
|
||||
};
|
||||
let decoder = Decoder::new(png.as_slice());
|
||||
let decoder = Decoder::new(Cursor::new(&png));
|
||||
let Err(err) = decoder.read_info() else {
|
||||
panic!("Expected an error")
|
||||
};
|
||||
@ -2476,21 +2509,25 @@ mod tests {
|
||||
/// `StreamingInput` can be used by tests to simulate a streaming input
|
||||
/// (e.g. a slow http response, where all bytes are not immediately available).
|
||||
#[derive(Clone)]
|
||||
struct StreamingInput(Rc<RefCell<StreamingInputState>>);
|
||||
struct StreamingInput {
|
||||
full_input: Vec<u8>,
|
||||
state: Rc<RefCell<StreamingInputState>>,
|
||||
}
|
||||
|
||||
struct StreamingInputState {
|
||||
full_input: Vec<u8>,
|
||||
current_pos: usize,
|
||||
available_len: usize,
|
||||
}
|
||||
|
||||
impl StreamingInput {
|
||||
fn new(full_input: Vec<u8>) -> Self {
|
||||
Self(Rc::new(RefCell::new(StreamingInputState {
|
||||
Self {
|
||||
full_input,
|
||||
current_pos: 0,
|
||||
available_len: 0,
|
||||
})))
|
||||
state: Rc::new(RefCell::new(StreamingInputState {
|
||||
current_pos: 0,
|
||||
available_len: 0,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
|
||||
@ -2500,14 +2537,14 @@ mod tests {
|
||||
}
|
||||
|
||||
fn expose_next_byte(&self) {
|
||||
let mut state = self.0.borrow_mut();
|
||||
assert!(state.available_len < state.full_input.len());
|
||||
let mut state = self.state.borrow_mut();
|
||||
assert!(state.available_len < self.full_input.len());
|
||||
state.available_len += 1;
|
||||
}
|
||||
|
||||
fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
|
||||
loop {
|
||||
self.0.borrow_mut().current_pos = 0;
|
||||
self.state.borrow_mut().current_pos = 0;
|
||||
match Decoder::new(self.clone()).read_info() {
|
||||
Ok(reader) => {
|
||||
break reader;
|
||||
@ -2522,24 +2559,49 @@ mod tests {
|
||||
|
||||
fn decode_full_input<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(Reader<&[u8]>) -> R,
|
||||
F: FnOnce(Reader<Cursor<&[u8]>>) -> R,
|
||||
{
|
||||
let state = self.0.borrow();
|
||||
let decoder = Decoder::new(state.full_input.as_slice());
|
||||
let decoder = Decoder::new(Cursor::new(&*self.full_input));
|
||||
f(decoder.read_info().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for StreamingInput {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let mut state = self.0.borrow_mut();
|
||||
let mut available_bytes = &state.full_input[state.current_pos..state.available_len];
|
||||
let mut state = self.state.borrow_mut();
|
||||
let mut available_bytes = &self.full_input[state.current_pos..state.available_len];
|
||||
let number_of_read_bytes = available_bytes.read(buf)?;
|
||||
state.current_pos += number_of_read_bytes;
|
||||
assert!(state.current_pos <= state.available_len);
|
||||
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]
|
||||
@ -2645,25 +2707,25 @@ mod tests {
|
||||
|
||||
/// Creates a ready-to-test [`Reader`] which decodes a PNG that contains:
|
||||
/// IHDR, IDAT, IEND.
|
||||
fn create_reader_of_ihdr_idat() -> Reader<VecDeque<u8>> {
|
||||
let mut png = VecDeque::new();
|
||||
fn create_reader_of_ihdr_idat() -> Reader<Cursor<Vec<u8>>> {
|
||||
let mut png = Vec::new();
|
||||
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:
|
||||
/// 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>> {
|
||||
let idat_width = 16;
|
||||
fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
|
||||
let width = 16;
|
||||
let mut fctl = crate::FrameControl {
|
||||
width: idat_width,
|
||||
height: idat_width, // same height and width
|
||||
width,
|
||||
height: width,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut png = VecDeque::new();
|
||||
let mut png = Vec::new();
|
||||
write_png_sig(&mut png);
|
||||
write_rgba8_ihdr_with_width(&mut png, idat_width);
|
||||
write_rgba8_ihdr_with_width(&mut png, width);
|
||||
write_actl(
|
||||
&mut png,
|
||||
&crate::AnimationControl {
|
||||
@ -2690,12 +2752,12 @@ mod tests {
|
||||
write_fdat(&mut png, 2, &fdat_data);
|
||||
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,
|
||||
/// 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 frame_data = generate_rgba8_with_width_and_height(width, width);
|
||||
let mut fctl = crate::FrameControl {
|
||||
@ -2704,7 +2766,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut png = VecDeque::new();
|
||||
let mut png = Vec::new();
|
||||
write_png_sig(&mut png);
|
||||
write_rgba8_ihdr_with_width(&mut png, width);
|
||||
write_actl(
|
||||
@ -2723,10 +2785,10 @@ mod tests {
|
||||
write_fdat(&mut png, 3, &frame_data);
|
||||
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
|
||||
.info()
|
||||
.frame_control
|
||||
@ -2966,4 +3028,28 @@ mod tests {
|
||||
&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 crate::common::BytesPerPixel;
|
||||
use crate::filter::{unfilter, FilterType};
|
||||
use crate::filter::{unfilter, RowFilter};
|
||||
|
||||
// Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows.
|
||||
pub(crate) struct UnfilteringBuffer {
|
||||
@ -96,7 +96,7 @@ impl UnfilteringBuffer {
|
||||
debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1));
|
||||
|
||||
// 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(),
|
||||
))?;
|
||||
let row = &mut row[1..rowlen];
|
@ -9,13 +9,14 @@ use flate2::write::ZlibEncoder;
|
||||
use crate::chunk::{self, ChunkType};
|
||||
use crate::common::{
|
||||
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::{
|
||||
encode_iso_8859_1, EncodableTextChunk, ITXtChunk, TEXtChunk, TextEncodingError, ZTXtChunk,
|
||||
};
|
||||
use crate::traits::WriteBytesExt;
|
||||
use crate::DeflateCompression;
|
||||
|
||||
pub type Result<T> = result::Result<T, EncodingError>;
|
||||
|
||||
@ -151,13 +152,13 @@ pub struct Encoder<'a, W: Write> {
|
||||
options: Options,
|
||||
}
|
||||
|
||||
/// Decoding options, internal type, forwarded to the Writer.
|
||||
/// Encoding options, internal type, forwarded to the Writer.
|
||||
#[derive(Default)]
|
||||
struct Options {
|
||||
filter: FilterType,
|
||||
adaptive_filter: AdaptiveFilterType,
|
||||
filter: Filter,
|
||||
sep_def_img: bool,
|
||||
validate_sequence: bool,
|
||||
compression: DeflateCompression,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Any ICC profiles will be ignored.
|
||||
@ -308,31 +297,28 @@ impl<'a, W: Write> Encoder<'a, W> {
|
||||
self.info.bit_depth = depth;
|
||||
}
|
||||
|
||||
/// Set compression parameters.
|
||||
///
|
||||
/// Accepts a `Compression` or any type that can transform into a `Compression`. Notably `deflate::Compression` and
|
||||
/// `deflate::CompressionOptions` which "just work".
|
||||
/// Set compression parameters, see [Compression] for the available options.
|
||||
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.
|
||||
///
|
||||
/// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for
|
||||
/// sample values based on the previous. For a potentially better compression ratio, at the
|
||||
/// 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.
|
||||
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||
/// for each row of the image.
|
||||
///
|
||||
/// 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;
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// Set the fraction of time every frame is going to be displayed, in seconds.
|
||||
@ -495,7 +481,6 @@ struct PartialInfo {
|
||||
color_type: ColorType,
|
||||
frame_control: Option<FrameControl>,
|
||||
animation_control: Option<AnimationControl>,
|
||||
compression: Compression,
|
||||
has_palette: bool,
|
||||
}
|
||||
|
||||
@ -508,39 +493,25 @@ impl PartialInfo {
|
||||
color_type: info.color_type,
|
||||
frame_control: info.frame_control,
|
||||
animation_control: info.animation_control,
|
||||
compression: info.compression,
|
||||
has_palette: info.palette.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bpp_in_prediction(&self) -> BytesPerPixel {
|
||||
// Passthrough
|
||||
self.to_info().bpp_in_prediction()
|
||||
BytesPerPixel::from_usize(self.bytes_per_pixel())
|
||||
}
|
||||
|
||||
fn bytes_per_pixel(&self) -> usize {
|
||||
self.color_type.bytes_per_pixel(self.bit_depth)
|
||||
}
|
||||
|
||||
fn raw_row_length(&self) -> usize {
|
||||
// Passthrough
|
||||
self.to_info().raw_row_length()
|
||||
self.raw_row_length_from_width(self.width)
|
||||
}
|
||||
|
||||
fn raw_row_length_from_width(&self, width: u32) -> usize {
|
||||
// Passthrough
|
||||
self.to_info().raw_row_length_from_width(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()
|
||||
}
|
||||
self.color_type
|
||||
.raw_row_length_from_width(self.bit_depth, width)
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,17 +560,100 @@ impl<W: Write> Writer<W> {
|
||||
));
|
||||
}
|
||||
|
||||
self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?; // PNG signature
|
||||
#[allow(deprecated)]
|
||||
info.encode(&mut self.w)?;
|
||||
self.encode_header(info)?;
|
||||
|
||||
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.
|
||||
///
|
||||
/// The chunk will have its CRC calculated and correctly. The data is not filtered in any way,
|
||||
/// but the chunk needs to be short enough to have its length encoded correctly.
|
||||
/// This function calculates the required CRC sum so this should not be included in the input
|
||||
/// `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<()> {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
@ -615,6 +669,31 @@ impl<W: Write> Writer<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.
|
||||
fn validate_new_image(&self) -> Result<()> {
|
||||
if !self.options.validate_sequence {
|
||||
@ -692,22 +771,23 @@ impl<W: Write> Writer<W> {
|
||||
|
||||
let bpp = self.info.bpp_in_prediction();
|
||||
let filter_method = self.options.filter;
|
||||
let adaptive_method = self.options.adaptive_filter;
|
||||
|
||||
let zlib_encoded = match self.info.compression {
|
||||
Compression::Fast => {
|
||||
let zlib_encoded = match self.options.compression {
|
||||
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 current = vec![0; in_len + 1];
|
||||
for line in data.chunks(in_len) {
|
||||
let filter_type = filter(
|
||||
filter_method,
|
||||
adaptive_method,
|
||||
bpp,
|
||||
prev,
|
||||
line,
|
||||
&mut current[1..],
|
||||
);
|
||||
let filter_type = filter(filter_method, bpp, prev, line, &mut current[1..]);
|
||||
|
||||
current[0] = filter_type as u8;
|
||||
compressor.write_data(¤t)?;
|
||||
@ -721,10 +801,7 @@ impl<W: Write> Writer<W> {
|
||||
// Write uncompressed data since the result from fast compression would take
|
||||
// more space than that.
|
||||
//
|
||||
// We always use FilterType::NoFilter here regardless of the filter method
|
||||
// requested by the user. Doing filtering again would only add performance
|
||||
// cost for both encoding and subsequent decoding, without improving the
|
||||
// compression ratio.
|
||||
// This is essentially a fallback to NoCompression.
|
||||
let mut compressor =
|
||||
fdeflate::StoredOnlyCompressor::new(std::io::Cursor::new(Vec::new()))?;
|
||||
for line in data.chunks(in_len) {
|
||||
@ -736,19 +813,13 @@ impl<W: Write> Writer<W> {
|
||||
compressed
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
DeflateCompression::Level(level) => {
|
||||
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) {
|
||||
let filter_type = filter(
|
||||
filter_method,
|
||||
adaptive_method,
|
||||
bpp,
|
||||
prev,
|
||||
line,
|
||||
&mut current,
|
||||
);
|
||||
let filter_type = filter(filter_method, bpp, prev, line, &mut current);
|
||||
|
||||
zlib.write_all(&[filter_type as u8])?;
|
||||
zlib.write_all(¤t)?;
|
||||
@ -818,25 +889,17 @@ impl<W: Write> Writer<W> {
|
||||
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
|
||||
/// sample values based on the previous. For a potentially better compression ratio, at the
|
||||
/// cost of more complex processing, try out [`FilterType::Paeth`].
|
||||
pub fn set_filter(&mut self, filter: FilterType) {
|
||||
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||
/// for each row of the image.
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// 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> {
|
||||
Borrowed(&'a mut Writer<W>),
|
||||
Owned(Writer<W>),
|
||||
@ -1342,10 +1375,9 @@ pub struct StreamWriter<'a, W: Write> {
|
||||
height: u32,
|
||||
|
||||
bpp: BytesPerPixel,
|
||||
filter: FilterType,
|
||||
adaptive_filter: AdaptiveFilterType,
|
||||
filter: Filter,
|
||||
fctl: Option<FrameControl>,
|
||||
compression: Compression,
|
||||
compression: DeflateCompression,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> StreamWriter<'a, W> {
|
||||
@ -1354,21 +1386,20 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
||||
width,
|
||||
height,
|
||||
frame_control: fctl,
|
||||
compression,
|
||||
..
|
||||
} = writer.info;
|
||||
|
||||
let bpp = writer.info.bpp_in_prediction();
|
||||
let in_len = writer.info.raw_row_length() - 1;
|
||||
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 curr_buf = vec![0; in_len];
|
||||
|
||||
let mut chunk_writer = ChunkWriter::new(writer, buf_len);
|
||||
let (line_len, to_write) = chunk_writer.next_frame_info();
|
||||
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 {
|
||||
writer: Wrapper::Zlib(zlib),
|
||||
@ -1379,7 +1410,6 @@ impl<'a, W: Write> StreamWriter<'a, W> {
|
||||
filter,
|
||||
width,
|
||||
height,
|
||||
adaptive_filter,
|
||||
line_len,
|
||||
to_write,
|
||||
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
|
||||
/// sample values based on the previous.
|
||||
/// The default filter is [`Filter::Adaptive`] which automatically selects the best filter
|
||||
/// for each row of the image.
|
||||
///
|
||||
/// For optimal compression ratio you should enable adaptive filtering
|
||||
/// instead of setting a single filter for the entire image, see
|
||||
/// [set_adaptive_filter](Self::set_adaptive_filter).
|
||||
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.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,
|
||||
/// 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
|
||||
match self.writer.take() {
|
||||
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);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -1659,7 +1677,6 @@ impl<'a, W: Write> Write for StreamWriter<'a, W> {
|
||||
let mut filtered = vec![0; self.curr_buf.len()];
|
||||
let filter_type = filter(
|
||||
self.filter,
|
||||
self.adaptive_filter,
|
||||
self.bpp,
|
||||
&self.prev_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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::Decoder;
|
||||
|
||||
use io::BufReader;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::cmp;
|
||||
use std::fs::File;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[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
|
||||
for _ in 0..10 {
|
||||
for _ in 0..5 {
|
||||
for path in glob::glob("tests/pngsuite/*.png")
|
||||
.unwrap()
|
||||
.map(|r| r.unwrap())
|
||||
@ -1750,42 +1758,55 @@ mod tests {
|
||||
}
|
||||
eprintln!("{}", path.display());
|
||||
// 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 buf = vec![0; reader.output_buffer_size()];
|
||||
let info = reader.next_frame(&mut buf).unwrap();
|
||||
// Encode decoded image
|
||||
let mut out = Vec::new();
|
||||
{
|
||||
let mut wrapper = RandomChunkWriter {
|
||||
rng: thread_rng(),
|
||||
w: &mut out,
|
||||
};
|
||||
use DeflateCompression::*;
|
||||
for compression in [NoCompression, FdeflateUltraFast, Level(4)] {
|
||||
// Encode decoded image
|
||||
let mut out = Vec::new();
|
||||
{
|
||||
let mut wrapper = RandomChunkWriter {
|
||||
rng: thread_rng(),
|
||||
w: &mut out,
|
||||
};
|
||||
|
||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||
encoder.set_color(info.color_type);
|
||||
encoder.set_depth(info.bit_depth);
|
||||
if let Some(palette) = &reader.info().palette {
|
||||
encoder.set_palette(palette.clone());
|
||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||
encoder.set_color(info.color_type);
|
||||
encoder.set_depth(info.bit_depth);
|
||||
encoder.set_deflate_compression(compression);
|
||||
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();
|
||||
encoder.write_image_data(&buf).unwrap();
|
||||
// Decode encoded decoded image
|
||||
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]
|
||||
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
|
||||
for _ in 0..10 {
|
||||
for _ in 0..5 {
|
||||
for path in glob::glob("tests/pngsuite/*.png")
|
||||
.unwrap()
|
||||
.map(|r| r.unwrap())
|
||||
@ -1795,41 +1816,45 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
// 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 buf = vec![0; reader.output_buffer_size()];
|
||||
let info = reader.next_frame(&mut buf).unwrap();
|
||||
// Encode decoded image
|
||||
let mut out = Vec::new();
|
||||
{
|
||||
let mut wrapper = RandomChunkWriter {
|
||||
rng: thread_rng(),
|
||||
w: &mut out,
|
||||
};
|
||||
use DeflateCompression::*;
|
||||
for compression in [NoCompression, FdeflateUltraFast, Level(4)] {
|
||||
// Encode decoded image
|
||||
let mut out = Vec::new();
|
||||
{
|
||||
let mut wrapper = RandomChunkWriter {
|
||||
rng: thread_rng(),
|
||||
w: &mut out,
|
||||
};
|
||||
|
||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||
encoder.set_color(info.color_type);
|
||||
encoder.set_depth(info.bit_depth);
|
||||
if let Some(palette) = &reader.info().palette {
|
||||
encoder.set_palette(palette.clone());
|
||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height);
|
||||
encoder.set_color(info.color_type);
|
||||
encoder.set_depth(info.bit_depth);
|
||||
encoder.set_deflate_compression(compression);
|
||||
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();
|
||||
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();
|
||||
// Decode encoded decoded image
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1839,7 +1864,7 @@ mod tests {
|
||||
for &bit_depth in &[1u8, 2, 4, 8] {
|
||||
// Do a reference decoding, choose a fitting palette image from pngsuite
|
||||
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 decoded_pixels = vec![0; reader.output_buffer_size()];
|
||||
@ -1864,7 +1889,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// 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 redecoded = vec![0; reader.output_buffer_size()];
|
||||
reader.next_frame(&mut redecoded).unwrap();
|
||||
@ -2056,7 +2081,7 @@ mod tests {
|
||||
fn all_filters_roundtrip() -> io::Result<()> {
|
||||
let pixel: Vec<_> = (0..48).collect();
|
||||
|
||||
let roundtrip = |filter: FilterType| -> io::Result<()> {
|
||||
let roundtrip = |filter: Filter| -> io::Result<()> {
|
||||
let mut buffer = vec![];
|
||||
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
||||
encoder.set_depth(BitDepth::Eight);
|
||||
@ -2076,11 +2101,11 @@ mod tests {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
roundtrip(FilterType::NoFilter)?;
|
||||
roundtrip(FilterType::Sub)?;
|
||||
roundtrip(FilterType::Up)?;
|
||||
roundtrip(FilterType::Avg)?;
|
||||
roundtrip(FilterType::Paeth)?;
|
||||
roundtrip(Filter::NoFilter)?;
|
||||
roundtrip(Filter::Sub)?;
|
||||
roundtrip(Filter::Up)?;
|
||||
roundtrip(Filter::Avg)?;
|
||||
roundtrip(Filter::Paeth)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -2094,7 +2119,7 @@ mod tests {
|
||||
let mut encoder = Encoder::new(&mut buffer, 4, 4);
|
||||
encoder.set_depth(BitDepth::Eight);
|
||||
encoder.set_color(ColorType::Rgb);
|
||||
encoder.set_filter(FilterType::Avg);
|
||||
encoder.set_filter(Filter::Avg);
|
||||
if let Some(gamma) = gamma {
|
||||
encoder.set_source_gamma(gamma);
|
||||
}
|
||||
@ -2103,7 +2128,7 @@ mod tests {
|
||||
let decoder = crate::Decoder::new(Cursor::new(buffer));
|
||||
let mut reader = decoder.read_info()?;
|
||||
assert_eq!(
|
||||
reader.info().source_gamma,
|
||||
reader.info().gamma(),
|
||||
gamma,
|
||||
"Deviation with gamma {:?}",
|
||||
gamma
|
||||
@ -2318,7 +2343,7 @@ mod tests {
|
||||
|
||||
let mut encoder = Encoder::new(&mut cursor, 8, 8);
|
||||
encoder.set_color(ColorType::Rgba);
|
||||
encoder.set_filter(FilterType::Paeth);
|
||||
encoder.set_filter(Filter::Paeth);
|
||||
let mut writer = encoder.write_header()?;
|
||||
let mut stream = writer.stream_writer()?;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::convert::TryInto;
|
||||
|
||||
use crate::common::BytesPerPixel;
|
||||
use crate::{common::BytesPerPixel, Compression};
|
||||
|
||||
/// SIMD helpers for `fn unfilter`
|
||||
///
|
||||
@ -60,7 +60,7 @@ mod simd {
|
||||
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
|
||||
#[derive(Default)]
|
||||
struct PaethState<T, const N: usize>
|
||||
@ -75,7 +75,7 @@ mod simd {
|
||||
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.
|
||||
/// 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])
|
||||
}
|
||||
|
||||
/// 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]) {
|
||||
debug_assert_eq!(prev_row.len(), curr_row.len());
|
||||
debug_assert_eq!(prev_row.len() % 3, 0);
|
||||
@ -155,7 +155,7 @@ mod simd {
|
||||
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>`
|
||||
/// 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])
|
||||
}
|
||||
|
||||
/// 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]) {
|
||||
debug_assert_eq!(prev_row.len(), curr_row.len());
|
||||
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.
|
||||
///
|
||||
/// 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)]
|
||||
#[repr(u8)]
|
||||
pub enum FilterType {
|
||||
pub(crate) enum RowFilter {
|
||||
NoFilter = 0,
|
||||
Sub = 1,
|
||||
Up = 2,
|
||||
@ -236,44 +280,33 @@ pub enum FilterType {
|
||||
Paeth = 4,
|
||||
}
|
||||
|
||||
impl Default for FilterType {
|
||||
impl Default for RowFilter {
|
||||
fn default() -> Self {
|
||||
FilterType::Sub
|
||||
RowFilter::Up
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterType {
|
||||
/// u8 -> Self. Temporary solution until Rust provides a canonical one.
|
||||
pub fn from_u8(n: u8) -> Option<FilterType> {
|
||||
impl RowFilter {
|
||||
pub fn from_u8(n: u8) -> Option<Self> {
|
||||
match n {
|
||||
0 => Some(FilterType::NoFilter),
|
||||
1 => Some(FilterType::Sub),
|
||||
2 => Some(FilterType::Up),
|
||||
3 => Some(FilterType::Avg),
|
||||
4 => Some(FilterType::Paeth),
|
||||
0 => Some(Self::NoFilter),
|
||||
1 => Some(Self::Sub),
|
||||
2 => Some(Self::Up),
|
||||
3 => Some(Self::Avg),
|
||||
4 => Some(Self::Paeth),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adaptive filtering tries every possible filter for each row and uses a heuristic to select the best one.
|
||||
/// This improves compression ratio, but makes encoding slightly slower.
|
||||
///
|
||||
/// It is recommended to use `Adaptive` whenever you care about compression ratio.
|
||||
/// Filtering is quite cheap compared to other parts of encoding, but can contribute
|
||||
/// to the compression ratio significantly.
|
||||
///
|
||||
/// `NonAdaptive` filtering is the default.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum AdaptiveFilterType {
|
||||
Adaptive,
|
||||
NonAdaptive,
|
||||
}
|
||||
|
||||
impl Default for AdaptiveFilterType {
|
||||
fn default() -> Self {
|
||||
AdaptiveFilterType::NonAdaptive
|
||||
pub fn from_method(strat: Filter) -> Option<Self> {
|
||||
match strat {
|
||||
Filter::NoFilter => Some(Self::NoFilter),
|
||||
Filter::Sub => Some(Self::Sub),
|
||||
Filter::Up => Some(Self::Up),
|
||||
Filter::Avg => Some(Self::Avg),
|
||||
Filter::Paeth => Some(Self::Paeth),
|
||||
Filter::Adaptive => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +346,7 @@ fn filter_paeth_stbi(a: u8, b: u8, c: u8) -> u8 {
|
||||
let hi = a.max(b);
|
||||
let t0 = if hi as i16 <= thresh { lo } else { c };
|
||||
let t1 = if thresh <= lo as i16 { hi } else { t0 };
|
||||
return t1;
|
||||
t1
|
||||
}
|
||||
|
||||
#[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(
|
||||
mut filter: FilterType,
|
||||
mut filter: RowFilter,
|
||||
tbpp: BytesPerPixel,
|
||||
previous: &[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 previous.is_empty() {
|
||||
@ -771,11 +804,9 @@ pub(crate) fn unfilter(
|
||||
}
|
||||
}
|
||||
BytesPerPixel::Four => {
|
||||
#[cfg(all(feature = "unstable", target_arch = "x86_64"))]
|
||||
{
|
||||
simd::unfilter_paeth_u8::<4>(previous, current);
|
||||
return;
|
||||
}
|
||||
// Using the `simd` module here has no effect on Linux
|
||||
// and appears to regress performance on Windows, so we don't use it here.
|
||||
// See https://github.com/image-rs/image-png/issues/567
|
||||
|
||||
let mut a_bpp = [0; 4];
|
||||
let mut c_bpp = [0; 4];
|
||||
@ -866,14 +897,14 @@ pub(crate) fn unfilter(
|
||||
}
|
||||
|
||||
fn filter_internal(
|
||||
method: FilterType,
|
||||
method: RowFilter,
|
||||
bpp: usize,
|
||||
len: usize,
|
||||
previous: &[u8],
|
||||
current: &[u8],
|
||||
output: &mut [u8],
|
||||
) -> FilterType {
|
||||
use self::FilterType::*;
|
||||
) -> RowFilter {
|
||||
use self::RowFilter::*;
|
||||
|
||||
// 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
|
||||
@ -1005,24 +1036,20 @@ fn filter_internal(
|
||||
}
|
||||
|
||||
pub(crate) fn filter(
|
||||
method: FilterType,
|
||||
adaptive: AdaptiveFilterType,
|
||||
method: Filter,
|
||||
bpp: BytesPerPixel,
|
||||
previous: &[u8],
|
||||
current: &[u8],
|
||||
output: &mut [u8],
|
||||
) -> FilterType {
|
||||
use FilterType::*;
|
||||
) -> RowFilter {
|
||||
use RowFilter::*;
|
||||
let bpp = bpp.into_usize();
|
||||
let len = current.len();
|
||||
|
||||
match adaptive {
|
||||
AdaptiveFilterType::NonAdaptive => {
|
||||
filter_internal(method, bpp, len, previous, current, output)
|
||||
}
|
||||
AdaptiveFilterType::Adaptive => {
|
||||
match method {
|
||||
Filter::Adaptive => {
|
||||
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() {
|
||||
filter_internal(filter, bpp, len, previous, current, output);
|
||||
let sum = sum_buffer(output);
|
||||
@ -1037,6 +1064,10 @@ pub(crate) fn filter(
|
||||
}
|
||||
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 current: Vec<_> = (0..LEN).collect();
|
||||
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()];
|
||||
filter(kind, adaptive, bpp, &previous, ¤t, &mut output);
|
||||
filter(kind.into(), bpp, &previous, ¤t, &mut output);
|
||||
unfilter(kind, bpp, &previous, &mut output);
|
||||
assert_eq!(
|
||||
output, expected,
|
||||
@ -1090,11 +1120,11 @@ mod test {
|
||||
};
|
||||
|
||||
let filters = [
|
||||
FilterType::NoFilter,
|
||||
FilterType::Sub,
|
||||
FilterType::Up,
|
||||
FilterType::Avg,
|
||||
FilterType::Paeth,
|
||||
RowFilter::NoFilter,
|
||||
RowFilter::Sub,
|
||||
RowFilter::Up,
|
||||
RowFilter::Avg,
|
||||
RowFilter::Paeth,
|
||||
];
|
||||
|
||||
let bpps = [
|
||||
@ -1139,11 +1169,10 @@ mod test {
|
||||
let previous: Vec<_> = (0..LEN).collect();
|
||||
let current: Vec<_> = (0..LEN).collect();
|
||||
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()];
|
||||
filter(kind, adaptive, bpp, &previous, ¤t, &mut output);
|
||||
filter(kind.into(), bpp, &previous, ¤t, &mut output);
|
||||
unfilter(kind, bpp, &previous, &mut output);
|
||||
assert_eq!(
|
||||
output, expected,
|
||||
@ -1153,11 +1182,11 @@ mod test {
|
||||
};
|
||||
|
||||
let filters = [
|
||||
FilterType::NoFilter,
|
||||
FilterType::Sub,
|
||||
FilterType::Up,
|
||||
FilterType::Avg,
|
||||
FilterType::Paeth,
|
||||
RowFilter::NoFilter,
|
||||
RowFilter::Sub,
|
||||
RowFilter::Up,
|
||||
RowFilter::Avg,
|
||||
RowFilter::Paeth,
|
||||
];
|
||||
|
||||
let bpps = [
|
@ -12,9 +12,10 @@
|
||||
//! ### Using the decoder
|
||||
//! ```
|
||||
//! use std::fs::File;
|
||||
//! use std::io::BufReader;
|
||||
//! // 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`.
|
||||
//! 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();
|
||||
//! // Allocate the output buffer.
|
||||
//! 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::{Decoder, InterlaceInfo, InterlacedRow, Limits, OutputInfo, Reader};
|
||||
pub use crate::encoder::{Encoder, EncodingError, StreamWriter, Writer};
|
||||
pub use crate::filter::{AdaptiveFilterType, FilterType};
|
||||
pub use crate::filter::Filter;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test_utils;
|
@ -5,9 +5,9 @@
|
||||
//! chunks. There are three kinds of text chunks.
|
||||
//! - `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
|
||||
//! 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
|
||||
//! 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
|
||||
//! to be used, but in practice these values are encountered anyway. This can
|
||||
@ -24,17 +24,13 @@
|
||||
//!
|
||||
//! ```
|
||||
//! use std::fs::File;
|
||||
//! use std::io::BufReader;
|
||||
//! use std::iter::FromIterator;
|
||||
//! use std::path::PathBuf;
|
||||
//!
|
||||
//! // Opening a png file that has a zTXt chunk
|
||||
//! let decoder = png::Decoder::new(
|
||||
//! File::open(PathBuf::from_iter([
|
||||
//! "tests",
|
||||
//! "text_chunk_examples",
|
||||
//! "ztxt_example.png",
|
||||
//! ]))
|
||||
//! .unwrap(),
|
||||
//! BufReader::new(File::open("tests/text_chunk_examples/ztxt_example.png").unwrap())
|
||||
//! );
|
||||
//! let mut reader = decoder.read_info().unwrap();
|
||||
//! // 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
|
||||
URL: https://crates.io/crates/png
|
||||
Version: 0.17.16
|
||||
Revision: fbf256669ff23594bf4c618b61fde6a52b79e088
|
||||
Version: 0.18.0-rc
|
||||
Revision: eb9b5d7f371b88f15aaca6a8d21c58b86c400d76
|
||||
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
|
||||
Security Critical: yes
|
||||
|
Reference in New Issue
Block a user