mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1573039 - Part 2: Revendor dependencies. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D41489 --HG-- rename : third_party/rust/image/src/hdr/hdr_decoder.rs => third_party/rust/image/src/hdr/decoder.rs rename : third_party/rust/image/src/hdr/hdr_encoder.rs => third_party/rust/image/src/hdr/encoder.rs extra : moz-landing-system : lando
This commit is contained in:
parent
4665febab6
commit
9c386d0de9
1
third_party/rust/crc32fast/.cargo-checksum.json
vendored
Normal file
1
third_party/rust/crc32fast/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"files":{"Cargo.toml":"c85c0241394119d8887c5e5624aba9a1a1fd21578f1a1e3f2a0d50d95d752cff","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"61d383b05b87d78f94d2937e2580cce47226d17823c0430fbcad09596537efcf","README.md":"c0891c7ff327441bf16da593b0e721951f9f6d10bb26f9356aba6a7b0b0c4575","benches/bench.rs":"9a45a7ebc8fecf7f9976bea0e3c00c13731c0b3566536b0bc83788986e801770","build.rs":"4ccc50c3da67eb27f0b622440d2b7aee2f73fa9c71884571f3c041122231d105","src/baseline.rs":"bbe8fe49ceccbf9749052fa9c2756cf95f0fc79a063e5d3b509e3600283464ea","src/combine.rs":"7147fc4002190d36d253ea5e194e0419035b087304bcb17887efe09a8a198815","src/lib.rs":"25c55822d7fd53ff1ff0769bcffbdbcade00d45ac042a541b7189c2e94b91ee7","src/specialized/aarch64.rs":"cc8097e68f1269cee32aa856b4f7e4ba7b7472df6c2f4cecd600d292a838fe83","src/specialized/mod.rs":"bc92450e8522e9df202b346b3a209153cbb0d6587804cbfd2b947fda0f190ed6","src/specialized/pclmulqdq.rs":"6ace803b42ff70a571fd8b5f3f7c2d5a836873ce28759381c2882319b8edba70","src/table.rs":"3201c520d97c5e2cf80b8a03d72fa2e3f1270bbdf93c2fbf85498a8ea39bc64b"},"package":"ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"}
|
41
third_party/rust/crc32fast/Cargo.toml
vendored
Normal file
41
third_party/rust/crc32fast/Cargo.toml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# 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]
|
||||
name = "crc32fast"
|
||||
version = "1.2.0"
|
||||
authors = ["Sam Rijs <srijs@airpost.net>", "Alex Crichton <alex@alexcrichton.com>"]
|
||||
description = "Fast, SIMD-accelerated CRC32 (IEEE) checksum computation"
|
||||
readme = "README.md"
|
||||
keywords = ["checksum", "crc", "crc32", "simd", "fast"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/srijs/rust-crc32fast"
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
harness = false
|
||||
[dependencies.cfg-if]
|
||||
version = "0.1"
|
||||
[dev-dependencies.bencher]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.quickcheck]
|
||||
version = "0.6"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.4"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
nightly = []
|
||||
std = []
|
202
third_party/rust/crc32fast/LICENSE-APACHE
vendored
Normal file
202
third_party/rust/crc32fast/LICENSE-APACHE
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
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.
|
||||
|
21
third_party/rust/crc32fast/LICENSE-MIT
vendored
Normal file
21
third_party/rust/crc32fast/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Sam Rijs, Alex Crichton and contributors
|
||||
|
||||
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.
|
81
third_party/rust/crc32fast/README.md
vendored
Normal file
81
third_party/rust/crc32fast/README.md
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
# crc32fast [![Build Status][travis-img]][travis] [![Crates.io][crates-img]][crates] [![Documentation][docs-img]][docs]
|
||||
|
||||
[travis-img]: https://travis-ci.com/srijs/rust-crc32fast.svg?branch=master
|
||||
[travis]: https://travis-ci.com/srijs/rust-crc32fast
|
||||
[crates-img]: https://img.shields.io/crates/v/crc32fast.svg
|
||||
[crates]: https://crates.io/crates/crc32fast
|
||||
[docs-img]: https://docs.rs/crc32fast/badge.svg
|
||||
[docs]: https://docs.rs/crc32fast
|
||||
|
||||
_Fast, SIMD-accelerated CRC32 (IEEE) checksum computation_
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
extern crate crc32fast;
|
||||
|
||||
use crc32fast::Hasher;
|
||||
|
||||
let mut hasher = Hasher::new();
|
||||
hasher.update(b"foo bar baz");
|
||||
let checksum = hasher.finalize();
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
This crate contains multiple CRC32 implementations:
|
||||
|
||||
- A fast baseline implementation which processes up to 16 bytes per iteration
|
||||
- An optimized implementation for modern `x86` using `sse` and `pclmulqdq` instructions
|
||||
- An optimized implementation for `aarch64` using `crc32` instructions
|
||||
|
||||
Calling the `Hasher::new` constructor at runtime will perform a feature detection to select the most
|
||||
optimal implementation for the current CPU feature set.
|
||||
|
||||
| crate | version | variant | ns/iter | MB/s |
|
||||
|-------------------------------------|---------|-----------|---------|------|
|
||||
| [crc](https://crates.io/crates/crc) | 1.8.1 | n/a | 4,926 | 207 |
|
||||
| crc32fast (this crate) | 1.0.0 | baseline | 683 | 1499 |
|
||||
| crc32fast (this crate) | 1.0.0 | pclmulqdq | 140 | 7314 |
|
||||
|
||||
## Memory Safety
|
||||
|
||||
Due to the use of SIMD intrinsics for the optimized implementations, this crate contains some amount of `unsafe` code.
|
||||
|
||||
In order to ensure memory safety, the relevant code has been fuzz tested using [afl.rs](https://github.com/rust-fuzz/afl.rs) with millions of iterations in both `debug` and `release` build settings. You can inspect the test setup in the `fuzz` sub-directory, which also has instructions on how to run the tests yourself.
|
||||
|
||||
On top of that, every commit is tested using an address sanitizer in CI to catch any out of bounds memory accesses.
|
||||
|
||||
Even though neither fuzzing not sanitization has revealed any safety bugs yet, please don't hesitate to file an issue if you run into any crashes or other unexpected behaviour.
|
||||
|
||||
## Available feature flags
|
||||
|
||||
### `std` (default: enabled)
|
||||
|
||||
This library supports being built without the Rust `std` library, which is useful for low-level use-cases such as embedded where no operating system is available. To build the crate in a `no_std` context, disable the default `std` feature.
|
||||
|
||||
Note: Because runtime CPU feature detection requires OS support, the specialized SIMD implementations will be unavailable when the `std` feature is disabled.
|
||||
|
||||
### `nightly` (default: disabled)
|
||||
|
||||
This feature flag enables unstable features that are only available on the `nightly` channel. Keep in mind that when enabling this feature flag, you
|
||||
might experience breaking changes when updating compiler versions.
|
||||
|
||||
Currently, enabling this feature flag will make the optimized `aarch64` implementation available.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this project by you, as defined in the Apache-2.0 license,
|
||||
shall be dual licensed as above, without any additional terms or conditions.
|
49
third_party/rust/crc32fast/benches/bench.rs
vendored
Normal file
49
third_party/rust/crc32fast/benches/bench.rs
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#[macro_use]
|
||||
extern crate bencher;
|
||||
extern crate crc32fast;
|
||||
extern crate rand;
|
||||
|
||||
use bencher::Bencher;
|
||||
use crc32fast::Hasher;
|
||||
use rand::Rng;
|
||||
|
||||
fn bench(b: &mut Bencher, size: usize, hasher_init: Hasher) {
|
||||
let mut bytes = vec![0u8; size];
|
||||
rand::thread_rng().fill_bytes(&mut bytes);
|
||||
|
||||
b.iter(|| {
|
||||
let mut hasher = hasher_init.clone();
|
||||
hasher.update(&bytes);
|
||||
bencher::black_box(hasher.finalize())
|
||||
});
|
||||
|
||||
b.bytes = size as u64;
|
||||
}
|
||||
|
||||
fn bench_kilobyte_baseline(b: &mut Bencher) {
|
||||
bench(b, 1024, Hasher::internal_new_baseline(0))
|
||||
}
|
||||
|
||||
fn bench_kilobyte_specialized(b: &mut Bencher) {
|
||||
bench(b, 1024, Hasher::internal_new_specialized(0).unwrap())
|
||||
}
|
||||
|
||||
fn bench_megabyte_baseline(b: &mut Bencher) {
|
||||
bench(b, 1024 * 1024, Hasher::internal_new_baseline(0))
|
||||
}
|
||||
|
||||
fn bench_megabyte_specialized(b: &mut Bencher) {
|
||||
bench(b, 1024 * 1024, Hasher::internal_new_specialized(0).unwrap())
|
||||
}
|
||||
|
||||
benchmark_group!(
|
||||
bench_baseline,
|
||||
bench_kilobyte_baseline,
|
||||
bench_megabyte_baseline
|
||||
);
|
||||
benchmark_group!(
|
||||
bench_specialized,
|
||||
bench_kilobyte_specialized,
|
||||
bench_megabyte_specialized
|
||||
);
|
||||
benchmark_main!(bench_baseline, bench_specialized);
|
35
third_party/rust/crc32fast/build.rs
vendored
Normal file
35
third_party/rust/crc32fast/build.rs
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let minor = match rustc_minor_version() {
|
||||
Some(n) => n,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if minor >= 27 {
|
||||
println!("cargo:rustc-cfg=crc32fast_stdarchx86");
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_minor_version() -> Option<u32> {
|
||||
macro_rules! otry {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Some(e) => e,
|
||||
None => return None,
|
||||
}
|
||||
};
|
||||
}
|
||||
let rustc = otry!(env::var_os("RUSTC"));
|
||||
let output = otry!(Command::new(rustc).arg("--version").output().ok());
|
||||
let version = otry!(str::from_utf8(&output.stdout).ok());
|
||||
let mut pieces = version.split('.');
|
||||
if pieces.next() != Some("rustc 1") {
|
||||
return None;
|
||||
}
|
||||
otry!(pieces.next()).parse().ok()
|
||||
}
|
94
third_party/rust/crc32fast/src/baseline.rs
vendored
Normal file
94
third_party/rust/crc32fast/src/baseline.rs
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
use table::CRC32_TABLE;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct State {
|
||||
state: u32,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new(state: u32) -> Self {
|
||||
State { state }
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
self.state = update_fast_16(self.state, buf);
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> u32 {
|
||||
self.state
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = 0;
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, other: u32, amount: u64) {
|
||||
self.state = ::combine::combine(self.state, other, amount);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_fast_16(prev: u32, mut buf: &[u8]) -> u32 {
|
||||
const UNROLL: usize = 4;
|
||||
const BYTES_AT_ONCE: usize = 16 * UNROLL;
|
||||
|
||||
let mut crc = !prev;
|
||||
|
||||
while buf.len() >= BYTES_AT_ONCE {
|
||||
for _ in 0..UNROLL {
|
||||
crc = CRC32_TABLE[0x0][buf[0xf] as usize]
|
||||
^ CRC32_TABLE[0x1][buf[0xe] as usize]
|
||||
^ CRC32_TABLE[0x2][buf[0xd] as usize]
|
||||
^ CRC32_TABLE[0x3][buf[0xc] as usize]
|
||||
^ CRC32_TABLE[0x4][buf[0xb] as usize]
|
||||
^ CRC32_TABLE[0x5][buf[0xa] as usize]
|
||||
^ CRC32_TABLE[0x6][buf[0x9] as usize]
|
||||
^ CRC32_TABLE[0x7][buf[0x8] as usize]
|
||||
^ CRC32_TABLE[0x8][buf[0x7] as usize]
|
||||
^ CRC32_TABLE[0x9][buf[0x6] as usize]
|
||||
^ CRC32_TABLE[0xa][buf[0x5] as usize]
|
||||
^ CRC32_TABLE[0xb][buf[0x4] as usize]
|
||||
^ CRC32_TABLE[0xc][buf[0x3] as usize ^ ((crc >> 0x18) & 0xFF) as usize]
|
||||
^ CRC32_TABLE[0xd][buf[0x2] as usize ^ ((crc >> 0x10) & 0xFF) as usize]
|
||||
^ CRC32_TABLE[0xe][buf[0x1] as usize ^ ((crc >> 0x08) & 0xFF) as usize]
|
||||
^ CRC32_TABLE[0xf][buf[0x0] as usize ^ ((crc >> 0x00) & 0xFF) as usize];
|
||||
buf = &buf[16..];
|
||||
}
|
||||
}
|
||||
|
||||
update_slow(!crc, buf)
|
||||
}
|
||||
|
||||
pub(crate) fn update_slow(prev: u32, buf: &[u8]) -> u32 {
|
||||
let mut crc = !prev;
|
||||
|
||||
for &byte in buf.iter() {
|
||||
crc = CRC32_TABLE[0][((crc as u8) ^ byte) as usize] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
!crc
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn slow() {
|
||||
assert_eq!(super::update_slow(0, b""), 0);
|
||||
|
||||
// test vectors from the iPXE project (input and output are bitwise negated)
|
||||
assert_eq!(super::update_slow(!0x12345678, b""), !0x12345678);
|
||||
assert_eq!(super::update_slow(!0xffffffff, b"hello world"), !0xf2b5ee7a);
|
||||
assert_eq!(super::update_slow(!0xffffffff, b"hello"), !0xc9ef5979);
|
||||
assert_eq!(super::update_slow(!0xc9ef5979, b" world"), !0xf2b5ee7a);
|
||||
|
||||
// Some vectors found on Rosetta code
|
||||
assert_eq!(super::update_slow(0, b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 0x190A55AD);
|
||||
assert_eq!(super::update_slow(0, b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"), 0xFF6CAB0B);
|
||||
assert_eq!(super::update_slow(0, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"), 0x91267E8A);
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn fast_16_is_the_same_as_slow(crc: u32, bytes: Vec<u8>) -> bool {
|
||||
super::update_fast_16(crc, &bytes) == super::update_slow(crc, &bytes)
|
||||
}
|
||||
}
|
||||
}
|
77
third_party/rust/crc32fast/src/combine.rs
vendored
Normal file
77
third_party/rust/crc32fast/src/combine.rs
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
const GF2_DIM: usize = 32;
|
||||
|
||||
fn gf2_matrix_times(mat: &[u32; GF2_DIM], mut vec: u32) -> u32 {
|
||||
let mut sum = 0;
|
||||
let mut idx = 0;
|
||||
while vec > 0 {
|
||||
if vec & 1 == 1 {
|
||||
sum ^= mat[idx];
|
||||
}
|
||||
vec >>= 1;
|
||||
idx += 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn gf2_matrix_square(square: &mut [u32; GF2_DIM], mat: &[u32; GF2_DIM]) {
|
||||
for n in 0..GF2_DIM {
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn combine(mut crc1: u32, crc2: u32, mut len2: u64) -> u32 {
|
||||
let mut row: u32;
|
||||
let mut even = [0u32; GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
let mut odd = [0u32; GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if len2 <= 0 {
|
||||
return crc1;
|
||||
}
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for n in 1..GF2_DIM {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(&mut even, &odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(&mut odd, &even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
loop {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(&mut even, &odd);
|
||||
if len2 & 1 == 1 {
|
||||
crc1 = gf2_matrix_times(&even, crc1);
|
||||
}
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if len2 == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(&mut odd, &even);
|
||||
if len2 & 1 == 1 {
|
||||
crc1 = gf2_matrix_times(&odd, crc1);
|
||||
}
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if len2 == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
178
third_party/rust/crc32fast/src/lib.rs
vendored
Normal file
178
third_party/rust/crc32fast/src/lib.rs
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use crc32fast::Hasher;
|
||||
//!
|
||||
//! let mut hasher = Hasher::new();
|
||||
//! hasher.update(b"foo bar baz");
|
||||
//! let checksum = hasher.finalize();
|
||||
//! ```
|
||||
//!
|
||||
//! ## Performance
|
||||
//!
|
||||
//! This crate contains multiple CRC32 implementations:
|
||||
//!
|
||||
//! - A fast baseline implementation which processes up to 16 bytes per iteration
|
||||
//! - An optimized implementation for modern `x86` using `sse` and `pclmulqdq` instructions
|
||||
//!
|
||||
//! Calling the `Hasher::new` constructor at runtime will perform a feature detection to select the most
|
||||
//! optimal implementation for the current CPU feature set.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(
|
||||
all(feature = "nightly", target_arch = "aarch64"),
|
||||
feature(stdsimd, aarch64_target_feature)
|
||||
)]
|
||||
|
||||
#[deny(missing_docs)]
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate quickcheck;
|
||||
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std as core;
|
||||
|
||||
use core::fmt;
|
||||
use core::hash;
|
||||
|
||||
mod baseline;
|
||||
mod combine;
|
||||
mod specialized;
|
||||
mod table;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum State {
|
||||
Baseline(baseline::State),
|
||||
Specialized(specialized::State),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Represents an in-progress CRC32 computation.
|
||||
pub struct Hasher {
|
||||
amount: u64,
|
||||
state: State,
|
||||
}
|
||||
|
||||
const DEFAULT_INIT_STATE: u32 = 0;
|
||||
|
||||
impl Hasher {
|
||||
/// Create a new `Hasher`.
|
||||
///
|
||||
/// This will perform a CPU feature detection at runtime to select the most
|
||||
/// optimal implementation for the current processor architecture.
|
||||
pub fn new() -> Self {
|
||||
Self::new_with_initial(DEFAULT_INIT_STATE)
|
||||
}
|
||||
|
||||
/// Create a new `Hasher` with an initial CRC32 state.
|
||||
///
|
||||
/// This works just like `Hasher::new`, except that it allows for an initial
|
||||
/// CRC32 state to be passed in.
|
||||
pub fn new_with_initial(init: u32) -> Self {
|
||||
Self::internal_new_specialized(init).unwrap_or_else(|| Self::internal_new_baseline(init))
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
// Internal-only API. Don't use.
|
||||
pub fn internal_new_baseline(init: u32) -> Self {
|
||||
Hasher {
|
||||
amount: 0,
|
||||
state: State::Baseline(baseline::State::new(init)),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
// Internal-only API. Don't use.
|
||||
pub fn internal_new_specialized(init: u32) -> Option<Self> {
|
||||
{
|
||||
if let Some(state) = specialized::State::new(init) {
|
||||
return Some(Hasher {
|
||||
amount: 0,
|
||||
state: State::Specialized(state),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Process the given byte slice and update the hash state.
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
self.amount += buf.len() as u64;
|
||||
match self.state {
|
||||
State::Baseline(ref mut state) => state.update(buf),
|
||||
State::Specialized(ref mut state) => state.update(buf),
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalize the hash state and return the computed CRC32 value.
|
||||
pub fn finalize(self) -> u32 {
|
||||
match self.state {
|
||||
State::Baseline(state) => state.finalize(),
|
||||
State::Specialized(state) => state.finalize(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset the hash state.
|
||||
pub fn reset(&mut self) {
|
||||
self.amount = 0;
|
||||
match self.state {
|
||||
State::Baseline(ref mut state) => state.reset(),
|
||||
State::Specialized(ref mut state) => state.reset(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Combine the hash state with the hash state for the subsequent block of bytes.
|
||||
pub fn combine(&mut self, other: &Self) {
|
||||
self.amount += other.amount;
|
||||
let other_crc = other.clone().finalize();
|
||||
match self.state {
|
||||
State::Baseline(ref mut state) => state.combine(other_crc, other.amount),
|
||||
State::Specialized(ref mut state) => state.combine(other_crc, other.amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Hasher {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("crc32fast::Hasher").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Hasher {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl hash::Hasher for Hasher {
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
self.update(bytes)
|
||||
}
|
||||
|
||||
fn finish(&self) -> u64 {
|
||||
u64::from(self.clone().finalize())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Hasher;
|
||||
|
||||
quickcheck! {
|
||||
fn combine(bytes_1: Vec<u8>, bytes_2: Vec<u8>) -> bool {
|
||||
let mut hash_a = Hasher::new();
|
||||
hash_a.update(&bytes_1);
|
||||
hash_a.update(&bytes_2);
|
||||
let mut hash_b = Hasher::new();
|
||||
hash_b.update(&bytes_2);
|
||||
let mut hash_c = Hasher::new();
|
||||
hash_c.update(&bytes_1);
|
||||
hash_c.combine(&hash_b);
|
||||
|
||||
hash_a.finalize() == hash_c.finalize()
|
||||
}
|
||||
}
|
||||
}
|
88
third_party/rust/crc32fast/src/specialized/aarch64.rs
vendored
Normal file
88
third_party/rust/crc32fast/src/specialized/aarch64.rs
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
use std::arch::aarch64 as arch;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct State {
|
||||
state: u32,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new(state: u32) -> Option<Self> {
|
||||
if is_aarch64_feature_detected!("crc") {
|
||||
// SAFETY: The conditions above ensure that all
|
||||
// required instructions are supported by the CPU.
|
||||
Some(Self { state })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
// SAFETY: The `State::new` constructor ensures that all
|
||||
// required instructions are supported by the CPU.
|
||||
self.state = unsafe { calculate(self.state, buf) }
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> u32 {
|
||||
self.state
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = 0;
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, other: u32, amount: u64) {
|
||||
self.state = ::combine::combine(self.state, other, amount);
|
||||
}
|
||||
}
|
||||
|
||||
// target_feature is necessary to allow rustc to inline the crc32* wrappers
|
||||
#[target_feature(enable = "crc")]
|
||||
pub unsafe fn calculate(crc: u32, data: &[u8]) -> u32 {
|
||||
let mut c32 = !crc;
|
||||
let (pre_quad, quads, post_quad) = data.align_to::<u64>();
|
||||
|
||||
c32 = pre_quad.iter().fold(c32, |acc, &b| arch::__crc32b(acc, b));
|
||||
|
||||
// unrolling increases performance by a lot
|
||||
let mut quad_iter = quads.chunks_exact(8);
|
||||
for chunk in &mut quad_iter {
|
||||
c32 = arch::__crc32d(c32, chunk[0]);
|
||||
c32 = arch::__crc32d(c32, chunk[1]);
|
||||
c32 = arch::__crc32d(c32, chunk[2]);
|
||||
c32 = arch::__crc32d(c32, chunk[3]);
|
||||
c32 = arch::__crc32d(c32, chunk[4]);
|
||||
c32 = arch::__crc32d(c32, chunk[5]);
|
||||
c32 = arch::__crc32d(c32, chunk[6]);
|
||||
c32 = arch::__crc32d(c32, chunk[7]);
|
||||
}
|
||||
c32 = quad_iter
|
||||
.remainder()
|
||||
.iter()
|
||||
.fold(c32, |acc, &q| arch::__crc32d(acc, q));
|
||||
|
||||
c32 = post_quad.iter().fold(c32, |acc, &b| arch::__crc32b(acc, b));
|
||||
|
||||
!c32
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
quickcheck! {
|
||||
fn check_against_baseline(init: u32, chunks: Vec<(Vec<u8>, usize)>) -> bool {
|
||||
let mut baseline = super::super::super::baseline::State::new(init);
|
||||
let mut aarch64 = super::State::new(init).expect("not supported");
|
||||
for (chunk, mut offset) in chunks {
|
||||
// simulate random alignments by offsetting the slice by up to 15 bytes
|
||||
offset &= 0xF;
|
||||
if chunk.len() <= offset {
|
||||
baseline.update(&chunk);
|
||||
aarch64.update(&chunk);
|
||||
} else {
|
||||
baseline.update(&chunk[offset..]);
|
||||
aarch64.update(&chunk[offset..]);
|
||||
}
|
||||
}
|
||||
aarch64.finalize() == baseline.finalize()
|
||||
}
|
||||
}
|
||||
}
|
36
third_party/rust/crc32fast/src/specialized/mod.rs
vendored
Normal file
36
third_party/rust/crc32fast/src/specialized/mod.rs
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
cfg_if! {
|
||||
if #[cfg(all(
|
||||
crc32fast_stdarchx86,
|
||||
any(target_arch = "x86", target_arch = "x86_64")
|
||||
))] {
|
||||
mod pclmulqdq;
|
||||
pub use self::pclmulqdq::State;
|
||||
} else if #[cfg(all(feature = "nightly", target_arch = "aarch64"))] {
|
||||
mod aarch64;
|
||||
pub use self::aarch64::State;
|
||||
} else {
|
||||
#[derive(Clone)]
|
||||
pub enum State {}
|
||||
impl State {
|
||||
pub fn new(_: u32) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn update(&mut self, _buf: &[u8]) {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> u32 {
|
||||
match self{}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, _other: u32, _amount: u64) {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
225
third_party/rust/crc32fast/src/specialized/pclmulqdq.rs
vendored
Normal file
225
third_party/rust/crc32fast/src/specialized/pclmulqdq.rs
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
#[cfg(target_arch = "x86")]
|
||||
use core::arch::x86 as arch;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use core::arch::x86_64 as arch;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct State {
|
||||
state: u32,
|
||||
}
|
||||
|
||||
impl State {
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub fn new(state: u32) -> Option<Self> {
|
||||
if cfg!(target_feature = "pclmulqdq")
|
||||
&& cfg!(target_feature = "sse2")
|
||||
&& cfg!(target_feature = "sse4.1")
|
||||
{
|
||||
// SAFETY: The conditions above ensure that all
|
||||
// required instructions are supported by the CPU.
|
||||
Some(Self { state })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn new(state: u32) -> Option<Self> {
|
||||
if is_x86_feature_detected!("pclmulqdq")
|
||||
&& is_x86_feature_detected!("sse2")
|
||||
&& is_x86_feature_detected!("sse4.1")
|
||||
{
|
||||
// SAFETY: The conditions above ensure that all
|
||||
// required instructions are supported by the CPU.
|
||||
Some(Self { state })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
// SAFETY: The `State::new` constructor ensures that all
|
||||
// required instructions are supported by the CPU.
|
||||
self.state = unsafe { calculate(self.state, buf) }
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> u32 {
|
||||
self.state
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = 0;
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, other: u32, amount: u64) {
|
||||
self.state = ::combine::combine(self.state, other, amount);
|
||||
}
|
||||
}
|
||||
|
||||
const K1: i64 = 0x154442bd4;
|
||||
const K2: i64 = 0x1c6e41596;
|
||||
const K3: i64 = 0x1751997d0;
|
||||
const K4: i64 = 0x0ccaa009e;
|
||||
const K5: i64 = 0x163cd6124;
|
||||
const K6: i64 = 0x1db710640;
|
||||
|
||||
const P_X: i64 = 0x1DB710641;
|
||||
const U_PRIME: i64 = 0x1F7011641;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
unsafe fn debug(s: &str, a: arch::__m128i) -> arch::__m128i {
|
||||
if false {
|
||||
union A {
|
||||
a: arch::__m128i,
|
||||
b: [u8; 16],
|
||||
}
|
||||
let x = A { a }.b;
|
||||
print!(" {:20} | ", s);
|
||||
for x in x.iter() {
|
||||
print!("{:02x} ", x);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
unsafe fn debug(_s: &str, a: arch::__m128i) -> arch::__m128i {
|
||||
a
|
||||
}
|
||||
|
||||
#[target_feature(enable = "pclmulqdq", enable = "sse2", enable = "sse4.1")]
|
||||
pub unsafe fn calculate(crc: u32, mut data: &[u8]) -> u32 {
|
||||
// In theory we can accelerate smaller chunks too, but for now just rely on
|
||||
// the fallback implementation as it's too much hassle and doesn't seem too
|
||||
// beneficial.
|
||||
if data.len() < 128 {
|
||||
return ::baseline::update_fast_16(crc, data);
|
||||
}
|
||||
|
||||
// Step 1: fold by 4 loop
|
||||
let mut x3 = get(&mut data);
|
||||
let mut x2 = get(&mut data);
|
||||
let mut x1 = get(&mut data);
|
||||
let mut x0 = get(&mut data);
|
||||
|
||||
// fold in our initial value, part of the incremental crc checksum
|
||||
x3 = arch::_mm_xor_si128(x3, arch::_mm_cvtsi32_si128(!crc as i32));
|
||||
|
||||
let k1k2 = arch::_mm_set_epi64x(K2, K1);
|
||||
while data.len() >= 64 {
|
||||
x3 = reduce128(x3, get(&mut data), k1k2);
|
||||
x2 = reduce128(x2, get(&mut data), k1k2);
|
||||
x1 = reduce128(x1, get(&mut data), k1k2);
|
||||
x0 = reduce128(x0, get(&mut data), k1k2);
|
||||
}
|
||||
|
||||
let k3k4 = arch::_mm_set_epi64x(K4, K3);
|
||||
let mut x = reduce128(x3, x2, k3k4);
|
||||
x = reduce128(x, x1, k3k4);
|
||||
x = reduce128(x, x0, k3k4);
|
||||
|
||||
// Step 2: fold by 1 loop
|
||||
while data.len() >= 16 {
|
||||
x = reduce128(x, get(&mut data), k3k4);
|
||||
}
|
||||
|
||||
debug("128 > 64 init", x);
|
||||
|
||||
// Perform step 3, reduction from 128 bits to 64 bits. This is
|
||||
// significantly different from the paper and basically doesn't follow it
|
||||
// at all. It's not really clear why, but implementations of this algorithm
|
||||
// in Chrome/Linux diverge in the same way. It is beyond me why this is
|
||||
// different than the paper, maybe the paper has like errata or something?
|
||||
// Unclear.
|
||||
//
|
||||
// It's also not clear to me what's actually happening here and/or why, but
|
||||
// algebraically what's happening is:
|
||||
//
|
||||
// x = (x[0:63] • K4) ^ x[64:127] // 96 bit result
|
||||
// x = ((x[0:31] as u64) • K5) ^ x[32:95] // 64 bit result
|
||||
//
|
||||
// It's... not clear to me what's going on here. The paper itself is pretty
|
||||
// vague on this part but definitely uses different constants at least.
|
||||
// It's not clear to me, reading the paper, where the xor operations are
|
||||
// happening or why things are shifting around. This implementation...
|
||||
// appears to work though!
|
||||
drop(K6);
|
||||
let x = arch::_mm_xor_si128(
|
||||
arch::_mm_clmulepi64_si128(x, k3k4, 0x10),
|
||||
arch::_mm_srli_si128(x, 8),
|
||||
);
|
||||
let x = arch::_mm_xor_si128(
|
||||
arch::_mm_clmulepi64_si128(
|
||||
arch::_mm_and_si128(x, arch::_mm_set_epi32(0, 0, 0, !0)),
|
||||
arch::_mm_set_epi64x(0, K5),
|
||||
0x00,
|
||||
),
|
||||
arch::_mm_srli_si128(x, 4),
|
||||
);
|
||||
debug("128 > 64 xx", x);
|
||||
|
||||
// Perform a Barrett reduction from our now 64 bits to 32 bits. The
|
||||
// algorithm for this is described at the end of the paper, and note that
|
||||
// this also implements the "bit reflected input" variant.
|
||||
let pu = arch::_mm_set_epi64x(U_PRIME, P_X);
|
||||
|
||||
// T1(x) = ⌊(R(x) % x^32)⌋ • μ
|
||||
let t1 = arch::_mm_clmulepi64_si128(
|
||||
arch::_mm_and_si128(x, arch::_mm_set_epi32(0, 0, 0, !0)),
|
||||
pu,
|
||||
0x10,
|
||||
);
|
||||
// T2(x) = ⌊(T1(x) % x^32)⌋ • P(x)
|
||||
let t2 = arch::_mm_clmulepi64_si128(
|
||||
arch::_mm_and_si128(t1, arch::_mm_set_epi32(0, 0, 0, !0)),
|
||||
pu,
|
||||
0x00,
|
||||
);
|
||||
// We're doing the bit-reflected variant, so get the upper 32-bits of the
|
||||
// 64-bit result instead of the lower 32-bits.
|
||||
//
|
||||
// C(x) = R(x) ^ T2(x) / x^32
|
||||
let c = arch::_mm_extract_epi32(arch::_mm_xor_si128(x, t2), 1) as u32;
|
||||
|
||||
if !data.is_empty() {
|
||||
::baseline::update_fast_16(!c, data)
|
||||
} else {
|
||||
!c
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn reduce128(a: arch::__m128i, b: arch::__m128i, keys: arch::__m128i) -> arch::__m128i {
|
||||
let t1 = arch::_mm_clmulepi64_si128(a, keys, 0x00);
|
||||
let t2 = arch::_mm_clmulepi64_si128(a, keys, 0x11);
|
||||
arch::_mm_xor_si128(arch::_mm_xor_si128(b, t1), t2)
|
||||
}
|
||||
|
||||
unsafe fn get(a: &mut &[u8]) -> arch::__m128i {
|
||||
debug_assert!(a.len() >= 16);
|
||||
let r = arch::_mm_loadu_si128(a.as_ptr() as *const arch::__m128i);
|
||||
*a = &a[16..];
|
||||
return r;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
quickcheck! {
|
||||
fn check_against_baseline(init: u32, chunks: Vec<(Vec<u8>, usize)>) -> bool {
|
||||
let mut baseline = super::super::super::baseline::State::new(init);
|
||||
let mut pclmulqdq = super::State::new(init).expect("not supported");
|
||||
for (chunk, mut offset) in chunks {
|
||||
// simulate random alignments by offsetting the slice by up to 15 bytes
|
||||
offset &= 0xF;
|
||||
if chunk.len() <= offset {
|
||||
baseline.update(&chunk);
|
||||
pclmulqdq.update(&chunk);
|
||||
} else {
|
||||
baseline.update(&chunk[offset..]);
|
||||
pclmulqdq.update(&chunk[offset..]);
|
||||
}
|
||||
}
|
||||
pclmulqdq.finalize() == baseline.finalize()
|
||||
}
|
||||
}
|
||||
}
|
626
third_party/rust/crc32fast/src/table.rs
vendored
Normal file
626
third_party/rust/crc32fast/src/table.rs
vendored
Normal file
@ -0,0 +1,626 @@
|
||||
pub const CRC32_TABLE: [[u32; 256]; 16] = [
|
||||
[
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
|
||||
0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
|
||||
0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
|
||||
0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
|
||||
0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,
|
||||
0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
|
||||
0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,
|
||||
0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
|
||||
0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
|
||||
0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,
|
||||
0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
|
||||
0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
|
||||
0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
|
||||
0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,
|
||||
0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
|
||||
0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
|
||||
0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
|
||||
0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786,
|
||||
0x4F4196C7, 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D,
|
||||
0x9E832D8E, 0x87981CCF, 0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, 0x2EAED755,
|
||||
0x37B5E614, 0x1C98B5D7, 0x05838496, 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A,
|
||||
0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, 0x958424A2, 0x8C9F15E3, 0xA7B24620,
|
||||
0xBEA97761, 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, 0x5D5DAEAA, 0x44469FEB,
|
||||
0x6F6BCC28, 0x7670FD69, 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, 0xDF4636F3,
|
||||
0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034,
|
||||
0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D,
|
||||
0x58DE2A3C, 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40,
|
||||
0xA623E883, 0xBF38D9C2, 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009,
|
||||
0x45D73148, 0x6EFA628B, 0x77E153CA, 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97,
|
||||
0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, 0x7262D75C, 0x6B79E61D, 0x4054B5DE,
|
||||
0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, 0x65FD6BA7, 0x7CE65AE6,
|
||||
0x57CB0925, 0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, 0xAD24E1AF,
|
||||
0xB43FD0EE, 0x9F12832D, 0x8609B26C, 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768,
|
||||
0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2, 0x52488DB3, 0x7965DE70,
|
||||
0x607EEF31, 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB,
|
||||
0xB1BC5478, 0xA8A76539, 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F,
|
||||
0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180,
|
||||
0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, 0x71418A1A, 0x685ABB5B, 0x4377E898,
|
||||
0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, 0xB9980012, 0xA0833153,
|
||||
0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, 0xAE07BCE9,
|
||||
0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E,
|
||||
0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167,
|
||||
0x299FA026, 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, 0x80A96BBC, 0x99B25AFD,
|
||||
0xB29F093E, 0xAB84387F, 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4,
|
||||
0x516BD0F5, 0x7A468336, 0x635DB277, 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D,
|
||||
0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189, 0x03235D46, 0x1A386C07, 0x31153FC4,
|
||||
0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, 0x8138C51F, 0x9823F45E,
|
||||
0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, 0x49E14F17,
|
||||
0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0,
|
||||
0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A,
|
||||
0x113F652B, 0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1,
|
||||
0xC0FDDE62, 0xD9E6EF23, 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9,
|
||||
0x69CB15F8, 0x42E6463B, 0x5BFD777A, 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876,
|
||||
0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2,
|
||||
0x054F1685, 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353,
|
||||
0x0A9E2D0A, 0x0B5C473D, 0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC,
|
||||
0x1AED619B, 0x18ABDFC2, 0x1969B5F5, 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91,
|
||||
0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, 0x384D46E0, 0x398F2CD7, 0x3BC9928E,
|
||||
0x3A0BF8B9, 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, 0x365E1758, 0x379C7D6F,
|
||||
0x35DAC336, 0x3418A901, 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, 0x246BE590,
|
||||
0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315,
|
||||
0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A,
|
||||
0x2F37A2AD, 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B,
|
||||
0x7417F172, 0x75D59B45, 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4,
|
||||
0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9,
|
||||
0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, 0x62AF7F08, 0x636D153F, 0x612BAB66,
|
||||
0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, 0x48D7CB20, 0x4915A117,
|
||||
0x4B531F4E, 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, 0x46C49A98,
|
||||
0x4706F0AF, 0x45404EF6, 0x448224C1, 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D,
|
||||
0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C, 0x523AAABB, 0x507C14E2,
|
||||
0x51BE7ED5, 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03,
|
||||
0x5E6F455A, 0x5FAD2F6D, 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C,
|
||||
0xE7FED96B, 0xE5B86732, 0xE47A0D05, 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461,
|
||||
0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E,
|
||||
0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, 0xF300E948, 0xF2C2837F,
|
||||
0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, 0xD9785D60,
|
||||
0xD8BA3757, 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5,
|
||||
0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A,
|
||||
0xD2241A5D, 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, 0xC25756CC, 0xC3953CFB,
|
||||
0xC1D382A2, 0xC011E895, 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774,
|
||||
0xCD866D43, 0xCFC0D31A, 0xCE02B92D, 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819,
|
||||
0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5, 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396,
|
||||
0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, 0x8D893530, 0x8C4B5F07,
|
||||
0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, 0x839A6488,
|
||||
0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D,
|
||||
0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12,
|
||||
0xACADC625, 0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3,
|
||||
0xA37CFDAA, 0xA2BE979D, 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C,
|
||||
0xB30FB13B, 0xB1490F62, 0xB08B6555, 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31,
|
||||
0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC,
|
||||
0x9DD738B9, 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD,
|
||||
0xE0DF7733, 0x58631056, 0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, 0xDF7BC0C8,
|
||||
0x67C7A7AD, 0x75720843, 0xCDCE6F26, 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E,
|
||||
0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, 0xA032AF3E, 0x188EC85B, 0x0A3B67B5,
|
||||
0xB28700D0, 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, 0x658687D1, 0xDD3AE0B4,
|
||||
0xCF8F4F5A, 0x7733283F, 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, 0xF02BF8A1,
|
||||
0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018,
|
||||
0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92,
|
||||
0xA848E8F7, 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F,
|
||||
0xBE7F07E1, 0x06C36084, 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785,
|
||||
0x697E80E0, 0x7BCB2F0E, 0xC377486B, 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C,
|
||||
0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, 0x0EB9274D, 0xB6054028, 0xA4B0EFC6,
|
||||
0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, 0x3B26F703, 0x839A9066,
|
||||
0x912F3F88, 0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, 0xFE92DFEC,
|
||||
0x462EB889, 0x549B1767, 0xEC277002, 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755,
|
||||
0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB, 0x5CE150AE, 0x4E54FF40,
|
||||
0xF6E89825, 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841,
|
||||
0x8BE0D7AF, 0x335CB0CA, 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C,
|
||||
0xDA874609, 0xC832E9E7, 0x708E8E82, 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A,
|
||||
0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, 0xBD40E1A4, 0x05FC86C1, 0x1749292F,
|
||||
0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, 0x78F4C94B, 0xC048AE2E,
|
||||
0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, 0x4D6B1905,
|
||||
0xF5D77E60, 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC,
|
||||
0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36,
|
||||
0x15080953, 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, 0x9210D9CD, 0x2AACBEA8,
|
||||
0x38191146, 0x80A57623, 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122,
|
||||
0xEF189647, 0xFDAD39A9, 0x45115ECC, 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8,
|
||||
0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF, 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62,
|
||||
0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, 0x2654B999, 0x9EE8DEFC,
|
||||
0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, 0xE3E09176,
|
||||
0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF,
|
||||
0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4,
|
||||
0x4BA87981, 0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5,
|
||||
0x36A0360B, 0x8E1C516E, 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0,
|
||||
0xB1B8E695, 0xA30D497B, 0x1BB12E1E, 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6,
|
||||
0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0,
|
||||
0xB220DC10, 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1,
|
||||
0xBF30BE61, 0x825097D1, 0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, 0x95603142,
|
||||
0xA80018F2, 0xEFA06222, 0xD2C04B92, 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693,
|
||||
0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, 0xC1C12F04, 0xFCA106B4, 0xBB017C64,
|
||||
0x866155D4, 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, 0xF1B164C5, 0xCCD14D75,
|
||||
0x8B7137A5, 0xB6111E15, 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, 0xA121B886,
|
||||
0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496,
|
||||
0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, 0x64D15587, 0x59B17C37, 0x1E1106E7,
|
||||
0x23712F57, 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739,
|
||||
0xD7B3ADE9, 0xEAD38459, 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548,
|
||||
0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B,
|
||||
0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, 0x0863840A, 0x3503ADBA, 0x72A3D76A,
|
||||
0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, 0x9932774D, 0xA4525EFD,
|
||||
0xE3F2242D, 0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, 0xA9423C8C,
|
||||
0x9422153C, 0xD3826FEC, 0xEEE2465C, 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C,
|
||||
0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, 0x0C52460F, 0x31326FBF, 0x7692156F,
|
||||
0x4BF23CDF, 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E,
|
||||
0x46E25EAE, 0x7B82771E, 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, 0x44661652,
|
||||
0x79063FE2, 0x3EA64532, 0x03C66C82, 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183,
|
||||
0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, 0xD1062710, 0xEC660EA0, 0xABC67470,
|
||||
0x96A65DC0, 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, 0xE1766CD1, 0xDC164561,
|
||||
0x9BB63FB1, 0xA6D61601, 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, 0x70279F96,
|
||||
0x4D47B626, 0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386,
|
||||
0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, 0xB5D77297, 0x88B75B27, 0xCF1721F7,
|
||||
0xF2770847, 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, 0xE547AED4, 0xD8278764,
|
||||
0x9F87FDB4, 0xA2E7D404, 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, 0xD537E515,
|
||||
0xE857CCA5, 0xAFF7B675, 0x92979FC5, 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B,
|
||||
0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB, 0xD965A31A, 0xE4058AAA, 0xA3A5F07A,
|
||||
0x9EC5D9CA, 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, 0x89F57F59, 0xB49556E9,
|
||||
0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, 0xB9853498,
|
||||
0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888,
|
||||
0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, 0xDD54611F, 0xE03448AF, 0xA794327F,
|
||||
0x9AF41BCF, 0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E,
|
||||
0x97E479BE, 0xAA84500E, 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D,
|
||||
0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C,
|
||||
0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D,
|
||||
0x1D0530B8, 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE,
|
||||
0x3A0A6170, 0xF156B2D5, 0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, 0x9847408D,
|
||||
0x531B9328, 0xD58FE186, 0x1ED33223, 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258,
|
||||
0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, 0x07AC0536, 0xCCF0D693, 0x4A64A43D,
|
||||
0x81387798, 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, 0xEBFF875B, 0x20A354FE,
|
||||
0xA6372650, 0x6D6BF5F5, 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, 0x047A07AD,
|
||||
0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715,
|
||||
0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, 0x73B8C7D6, 0xB8E41473, 0x3E7066DD,
|
||||
0xF52CB578, 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF,
|
||||
0xD901E971, 0x125D3AD4, 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17,
|
||||
0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59,
|
||||
0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, 0xE0DD8A9A, 0x2B81593F, 0xAD152B91,
|
||||
0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, 0x08F40F5A, 0xC3A8DCFF,
|
||||
0x453CAE51, 0x8E607DF4, 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, 0xE4A78D37,
|
||||
0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F,
|
||||
0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC,
|
||||
0x16273D79, 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F,
|
||||
0x31286CB1, 0xFA74BF14, 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, 0x852156CE,
|
||||
0x4E7D856B, 0xC8E9F7C5, 0x03B52460, 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B,
|
||||
0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, 0x1D661643, 0xD63AC5E6, 0x50AEB748,
|
||||
0x9BF264ED, 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, 0xF135942E, 0x3A69478B,
|
||||
0xBCFD3525, 0x77A1E680, 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, 0x191C11EE,
|
||||
0xD240C24B, 0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156,
|
||||
0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, 0x6EDED195, 0xA5820230, 0x2316709E,
|
||||
0xE84AA33B, 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, 0x815B5163, 0x4A0782C6,
|
||||
0xCC93F068, 0x07CF23CD, 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, 0x6D08D30E,
|
||||
0xA65400AB, 0x20C07205, 0xEB9CA1A0, 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A,
|
||||
0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C, 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2,
|
||||
0x7B2FEE77, 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, 0x123E1C2F, 0xD962CF8A,
|
||||
0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, 0xFE6D9E42,
|
||||
0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA,
|
||||
0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, 0x8DD55994, 0x46898A31, 0xC01DF89F,
|
||||
0x0B412B3A, 0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C,
|
||||
0x2C4E7AF2, 0xE712A957, 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F,
|
||||
0x455F88AA, 0xC3CBFA04, 0x089729A1, 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA,
|
||||
0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A,
|
||||
0xC5A73E8E, 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0,
|
||||
0x503F7B5D, 0xF64870E9, 0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, 0x9391B8DD,
|
||||
0x35E6B369, 0x040EA9F4, 0xA279A240, 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834,
|
||||
0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, 0xCFBD399C, 0x69CA3228, 0x582228B5,
|
||||
0xFE552301, 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, 0xFC5277FB, 0x5A257C4F,
|
||||
0x6BCD66D2, 0xCDBA6D66, 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, 0xA863A552,
|
||||
0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC,
|
||||
0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F,
|
||||
0x5E2BD5BB, 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE,
|
||||
0x27DB4043, 0x81AC4BF7, 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D,
|
||||
0x25DC14B9, 0x14340E24, 0xB2430590, 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A,
|
||||
0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, 0x103AA7D0, 0xB64DAC64, 0x87A5B6F9,
|
||||
0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, 0x8BB64CE5, 0x2DC14751,
|
||||
0x1C295DCC, 0xBA5E5678, 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, 0xB8590282,
|
||||
0x1E2E0936, 0x2FC613AB, 0x89B1181F, 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C,
|
||||
0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, 0x1827F438, 0xBE50FF8C, 0x8FB8E511,
|
||||
0x29CFEEA5, 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB,
|
||||
0xBC57AB76, 0x1A20A0C2, 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, 0x7C59CEE1,
|
||||
0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08,
|
||||
0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, 0xEFC8763C, 0x49BF7D88, 0x78576715,
|
||||
0xDE206CA1, 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, 0xDC27385B, 0x7A5033EF,
|
||||
0x4BB82972, 0xEDCF22C6, 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, 0x47ABD36E,
|
||||
0xE1DCD8DA, 0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0,
|
||||
0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, 0x800BB91A, 0x267CB2AE, 0x1794A833,
|
||||
0xB1E3A387, 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, 0xD43A6BB3, 0x724D6007,
|
||||
0x43A57A9A, 0xE5D2712E, 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, 0xE7D525D4,
|
||||
0x41A22E60, 0x704A34FD, 0xD63D3F49, 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516,
|
||||
0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105, 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5,
|
||||
0xCE1ACB71, 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, 0xABC30345, 0x0DB408F1,
|
||||
0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, 0x982C4D22,
|
||||
0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC,
|
||||
0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, 0xF7EF8204, 0x519889B0, 0x6070932D,
|
||||
0xC6079899, 0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7,
|
||||
0x539FDD4A, 0xF5E8D6FE, 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA,
|
||||
0x3646157E, 0x07AE0FE3, 0xA1D90457, 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23,
|
||||
0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987,
|
||||
0x0AC50919, 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1,
|
||||
0x158A1232, 0xD92012AC, 0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, 0xF8F13FD1,
|
||||
0x345B3F4F, 0xBAD438AC, 0x767E3832, 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D,
|
||||
0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, 0xF9766256, 0x35DC62C8, 0xBB53652B,
|
||||
0x77F965B5, 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, 0x2A9379E3, 0xE639797D,
|
||||
0x68B67E9E, 0xA41C7E00, 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, 0x85CD537D,
|
||||
0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64,
|
||||
0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, 0xD2624632, 0x1EC846AC, 0x9047414F,
|
||||
0x5CED41D1, 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89,
|
||||
0xEFF2CB6A, 0x2358CBF4, 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2,
|
||||
0xB298D73C, 0x3C17D0DF, 0xF0BDD041, 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425,
|
||||
0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, 0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E,
|
||||
0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, 0xD0EBA0BB, 0x1C41A025,
|
||||
0x92CEA7C6, 0x5E64A758, 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, 0x030EBB0E,
|
||||
0xCFA4BB90, 0x412BBC73, 0x8D81BCED, 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217,
|
||||
0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817,
|
||||
0xA6959889, 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441,
|
||||
0xB9DA83A2, 0x7570833C, 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, 0xD7718B20,
|
||||
0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C,
|
||||
0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C,
|
||||
0xA10FB312, 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, 0xFC65AF44, 0x30CFAFDA,
|
||||
0xBE40A839, 0x72EAA8A7, 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, 0xAA4DE78C,
|
||||
0x66E7E712, 0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95,
|
||||
0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE,
|
||||
0x736DF520, 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, 0x52BCD85D, 0x9E16D8C3,
|
||||
0x1099DF20, 0xDC33DFBE, 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8,
|
||||
0x4DF3C376, 0xC37CC495, 0x0FD6C40B, 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4,
|
||||
0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E, 0xA9435C82, 0x65E95C1C, 0xEB665BFF,
|
||||
0x27CC5B61, 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, 0x061D761C, 0xCAB77682,
|
||||
0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, 0xD5F86DA9,
|
||||
0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0,
|
||||
0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, 0x079A2B9B, 0xCB302B05, 0x45BF2CE6,
|
||||
0x89152C78, 0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0,
|
||||
0x965A3753, 0x5AF037CD, 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0,
|
||||
0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C,
|
||||
0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x177B1443, 0x2EF62886, 0x398D3CC5, 0x5DEC510C, 0x4A97454F, 0x731A798A,
|
||||
0x64616DC9, 0xBBD8A218, 0xACA3B65B, 0x952E8A9E, 0x82559EDD, 0xE634F314, 0xF14FE757,
|
||||
0xC8C2DB92, 0xDFB9CFD1, 0xACC04271, 0xBBBB5632, 0x82366AF7, 0x954D7EB4, 0xF12C137D,
|
||||
0xE657073E, 0xDFDA3BFB, 0xC8A12FB8, 0x1718E069, 0x0063F42A, 0x39EEC8EF, 0x2E95DCAC,
|
||||
0x4AF4B165, 0x5D8FA526, 0x640299E3, 0x73798DA0, 0x82F182A3, 0x958A96E0, 0xAC07AA25,
|
||||
0xBB7CBE66, 0xDF1DD3AF, 0xC866C7EC, 0xF1EBFB29, 0xE690EF6A, 0x392920BB, 0x2E5234F8,
|
||||
0x17DF083D, 0x00A41C7E, 0x64C571B7, 0x73BE65F4, 0x4A335931, 0x5D484D72, 0x2E31C0D2,
|
||||
0x394AD491, 0x00C7E854, 0x17BCFC17, 0x73DD91DE, 0x64A6859D, 0x5D2BB958, 0x4A50AD1B,
|
||||
0x95E962CA, 0x82927689, 0xBB1F4A4C, 0xAC645E0F, 0xC80533C6, 0xDF7E2785, 0xE6F31B40,
|
||||
0xF1880F03, 0xDE920307, 0xC9E91744, 0xF0642B81, 0xE71F3FC2, 0x837E520B, 0x94054648,
|
||||
0xAD887A8D, 0xBAF36ECE, 0x654AA11F, 0x7231B55C, 0x4BBC8999, 0x5CC79DDA, 0x38A6F013,
|
||||
0x2FDDE450, 0x1650D895, 0x012BCCD6, 0x72524176, 0x65295535, 0x5CA469F0, 0x4BDF7DB3,
|
||||
0x2FBE107A, 0x38C50439, 0x014838FC, 0x16332CBF, 0xC98AE36E, 0xDEF1F72D, 0xE77CCBE8,
|
||||
0xF007DFAB, 0x9466B262, 0x831DA621, 0xBA909AE4, 0xADEB8EA7, 0x5C6381A4, 0x4B1895E7,
|
||||
0x7295A922, 0x65EEBD61, 0x018FD0A8, 0x16F4C4EB, 0x2F79F82E, 0x3802EC6D, 0xE7BB23BC,
|
||||
0xF0C037FF, 0xC94D0B3A, 0xDE361F79, 0xBA5772B0, 0xAD2C66F3, 0x94A15A36, 0x83DA4E75,
|
||||
0xF0A3C3D5, 0xE7D8D796, 0xDE55EB53, 0xC92EFF10, 0xAD4F92D9, 0xBA34869A, 0x83B9BA5F,
|
||||
0x94C2AE1C, 0x4B7B61CD, 0x5C00758E, 0x658D494B, 0x72F65D08, 0x169730C1, 0x01EC2482,
|
||||
0x38611847, 0x2F1A0C04, 0x6655004F, 0x712E140C, 0x48A328C9, 0x5FD83C8A, 0x3BB95143,
|
||||
0x2CC24500, 0x154F79C5, 0x02346D86, 0xDD8DA257, 0xCAF6B614, 0xF37B8AD1, 0xE4009E92,
|
||||
0x8061F35B, 0x971AE718, 0xAE97DBDD, 0xB9ECCF9E, 0xCA95423E, 0xDDEE567D, 0xE4636AB8,
|
||||
0xF3187EFB, 0x97791332, 0x80020771, 0xB98F3BB4, 0xAEF42FF7, 0x714DE026, 0x6636F465,
|
||||
0x5FBBC8A0, 0x48C0DCE3, 0x2CA1B12A, 0x3BDAA569, 0x025799AC, 0x152C8DEF, 0xE4A482EC,
|
||||
0xF3DF96AF, 0xCA52AA6A, 0xDD29BE29, 0xB948D3E0, 0xAE33C7A3, 0x97BEFB66, 0x80C5EF25,
|
||||
0x5F7C20F4, 0x480734B7, 0x718A0872, 0x66F11C31, 0x029071F8, 0x15EB65BB, 0x2C66597E,
|
||||
0x3B1D4D3D, 0x4864C09D, 0x5F1FD4DE, 0x6692E81B, 0x71E9FC58, 0x15889191, 0x02F385D2,
|
||||
0x3B7EB917, 0x2C05AD54, 0xF3BC6285, 0xE4C776C6, 0xDD4A4A03, 0xCA315E40, 0xAE503389,
|
||||
0xB92B27CA, 0x80A61B0F, 0x97DD0F4C, 0xB8C70348, 0xAFBC170B, 0x96312BCE, 0x814A3F8D,
|
||||
0xE52B5244, 0xF2504607, 0xCBDD7AC2, 0xDCA66E81, 0x031FA150, 0x1464B513, 0x2DE989D6,
|
||||
0x3A929D95, 0x5EF3F05C, 0x4988E41F, 0x7005D8DA, 0x677ECC99, 0x14074139, 0x037C557A,
|
||||
0x3AF169BF, 0x2D8A7DFC, 0x49EB1035, 0x5E900476, 0x671D38B3, 0x70662CF0, 0xAFDFE321,
|
||||
0xB8A4F762, 0x8129CBA7, 0x9652DFE4, 0xF233B22D, 0xE548A66E, 0xDCC59AAB, 0xCBBE8EE8,
|
||||
0x3A3681EB, 0x2D4D95A8, 0x14C0A96D, 0x03BBBD2E, 0x67DAD0E7, 0x70A1C4A4, 0x492CF861,
|
||||
0x5E57EC22, 0x81EE23F3, 0x969537B0, 0xAF180B75, 0xB8631F36, 0xDC0272FF, 0xCB7966BC,
|
||||
0xF2F45A79, 0xE58F4E3A, 0x96F6C39A, 0x818DD7D9, 0xB800EB1C, 0xAF7BFF5F, 0xCB1A9296,
|
||||
0xDC6186D5, 0xE5ECBA10, 0xF297AE53, 0x2D2E6182, 0x3A5575C1, 0x03D84904, 0x14A35D47,
|
||||
0x70C2308E, 0x67B924CD, 0x5E341808, 0x494F0C4B,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xEFC26B3E, 0x04F5D03D, 0xEB37BB03, 0x09EBA07A, 0xE629CB44, 0x0D1E7047,
|
||||
0xE2DC1B79, 0x13D740F4, 0xFC152BCA, 0x172290C9, 0xF8E0FBF7, 0x1A3CE08E, 0xF5FE8BB0,
|
||||
0x1EC930B3, 0xF10B5B8D, 0x27AE81E8, 0xC86CEAD6, 0x235B51D5, 0xCC993AEB, 0x2E452192,
|
||||
0xC1874AAC, 0x2AB0F1AF, 0xC5729A91, 0x3479C11C, 0xDBBBAA22, 0x308C1121, 0xDF4E7A1F,
|
||||
0x3D926166, 0xD2500A58, 0x3967B15B, 0xD6A5DA65, 0x4F5D03D0, 0xA09F68EE, 0x4BA8D3ED,
|
||||
0xA46AB8D3, 0x46B6A3AA, 0xA974C894, 0x42437397, 0xAD8118A9, 0x5C8A4324, 0xB348281A,
|
||||
0x587F9319, 0xB7BDF827, 0x5561E35E, 0xBAA38860, 0x51943363, 0xBE56585D, 0x68F38238,
|
||||
0x8731E906, 0x6C065205, 0x83C4393B, 0x61182242, 0x8EDA497C, 0x65EDF27F, 0x8A2F9941,
|
||||
0x7B24C2CC, 0x94E6A9F2, 0x7FD112F1, 0x901379CF, 0x72CF62B6, 0x9D0D0988, 0x763AB28B,
|
||||
0x99F8D9B5, 0x9EBA07A0, 0x71786C9E, 0x9A4FD79D, 0x758DBCA3, 0x9751A7DA, 0x7893CCE4,
|
||||
0x93A477E7, 0x7C661CD9, 0x8D6D4754, 0x62AF2C6A, 0x89989769, 0x665AFC57, 0x8486E72E,
|
||||
0x6B448C10, 0x80733713, 0x6FB15C2D, 0xB9148648, 0x56D6ED76, 0xBDE15675, 0x52233D4B,
|
||||
0xB0FF2632, 0x5F3D4D0C, 0xB40AF60F, 0x5BC89D31, 0xAAC3C6BC, 0x4501AD82, 0xAE361681,
|
||||
0x41F47DBF, 0xA32866C6, 0x4CEA0DF8, 0xA7DDB6FB, 0x481FDDC5, 0xD1E70470, 0x3E256F4E,
|
||||
0xD512D44D, 0x3AD0BF73, 0xD80CA40A, 0x37CECF34, 0xDCF97437, 0x333B1F09, 0xC2304484,
|
||||
0x2DF22FBA, 0xC6C594B9, 0x2907FF87, 0xCBDBE4FE, 0x24198FC0, 0xCF2E34C3, 0x20EC5FFD,
|
||||
0xF6498598, 0x198BEEA6, 0xF2BC55A5, 0x1D7E3E9B, 0xFFA225E2, 0x10604EDC, 0xFB57F5DF,
|
||||
0x14959EE1, 0xE59EC56C, 0x0A5CAE52, 0xE16B1551, 0x0EA97E6F, 0xEC756516, 0x03B70E28,
|
||||
0xE880B52B, 0x0742DE15, 0xE6050901, 0x09C7623F, 0xE2F0D93C, 0x0D32B202, 0xEFEEA97B,
|
||||
0x002CC245, 0xEB1B7946, 0x04D91278, 0xF5D249F5, 0x1A1022CB, 0xF12799C8, 0x1EE5F2F6,
|
||||
0xFC39E98F, 0x13FB82B1, 0xF8CC39B2, 0x170E528C, 0xC1AB88E9, 0x2E69E3D7, 0xC55E58D4,
|
||||
0x2A9C33EA, 0xC8402893, 0x278243AD, 0xCCB5F8AE, 0x23779390, 0xD27CC81D, 0x3DBEA323,
|
||||
0xD6891820, 0x394B731E, 0xDB976867, 0x34550359, 0xDF62B85A, 0x30A0D364, 0xA9580AD1,
|
||||
0x469A61EF, 0xADADDAEC, 0x426FB1D2, 0xA0B3AAAB, 0x4F71C195, 0xA4467A96, 0x4B8411A8,
|
||||
0xBA8F4A25, 0x554D211B, 0xBE7A9A18, 0x51B8F126, 0xB364EA5F, 0x5CA68161, 0xB7913A62,
|
||||
0x5853515C, 0x8EF68B39, 0x6134E007, 0x8A035B04, 0x65C1303A, 0x871D2B43, 0x68DF407D,
|
||||
0x83E8FB7E, 0x6C2A9040, 0x9D21CBCD, 0x72E3A0F3, 0x99D41BF0, 0x761670CE, 0x94CA6BB7,
|
||||
0x7B080089, 0x903FBB8A, 0x7FFDD0B4, 0x78BF0EA1, 0x977D659F, 0x7C4ADE9C, 0x9388B5A2,
|
||||
0x7154AEDB, 0x9E96C5E5, 0x75A17EE6, 0x9A6315D8, 0x6B684E55, 0x84AA256B, 0x6F9D9E68,
|
||||
0x805FF556, 0x6283EE2F, 0x8D418511, 0x66763E12, 0x89B4552C, 0x5F118F49, 0xB0D3E477,
|
||||
0x5BE45F74, 0xB426344A, 0x56FA2F33, 0xB938440D, 0x520FFF0E, 0xBDCD9430, 0x4CC6CFBD,
|
||||
0xA304A483, 0x48331F80, 0xA7F174BE, 0x452D6FC7, 0xAAEF04F9, 0x41D8BFFA, 0xAE1AD4C4,
|
||||
0x37E20D71, 0xD820664F, 0x3317DD4C, 0xDCD5B672, 0x3E09AD0B, 0xD1CBC635, 0x3AFC7D36,
|
||||
0xD53E1608, 0x24354D85, 0xCBF726BB, 0x20C09DB8, 0xCF02F686, 0x2DDEEDFF, 0xC21C86C1,
|
||||
0x292B3DC2, 0xC6E956FC, 0x104C8C99, 0xFF8EE7A7, 0x14B95CA4, 0xFB7B379A, 0x19A72CE3,
|
||||
0xF66547DD, 0x1D52FCDE, 0xF29097E0, 0x039BCC6D, 0xEC59A753, 0x076E1C50, 0xE8AC776E,
|
||||
0x0A706C17, 0xE5B20729, 0x0E85BC2A, 0xE147D714,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xC18EDFC0, 0x586CB9C1, 0x99E26601, 0xB0D97382, 0x7157AC42, 0xE8B5CA43,
|
||||
0x293B1583, 0xBAC3E145, 0x7B4D3E85, 0xE2AF5884, 0x23218744, 0x0A1A92C7, 0xCB944D07,
|
||||
0x52762B06, 0x93F8F4C6, 0xAEF6C4CB, 0x6F781B0B, 0xF69A7D0A, 0x3714A2CA, 0x1E2FB749,
|
||||
0xDFA16889, 0x46430E88, 0x87CDD148, 0x1435258E, 0xD5BBFA4E, 0x4C599C4F, 0x8DD7438F,
|
||||
0xA4EC560C, 0x656289CC, 0xFC80EFCD, 0x3D0E300D, 0x869C8FD7, 0x47125017, 0xDEF03616,
|
||||
0x1F7EE9D6, 0x3645FC55, 0xF7CB2395, 0x6E294594, 0xAFA79A54, 0x3C5F6E92, 0xFDD1B152,
|
||||
0x6433D753, 0xA5BD0893, 0x8C861D10, 0x4D08C2D0, 0xD4EAA4D1, 0x15647B11, 0x286A4B1C,
|
||||
0xE9E494DC, 0x7006F2DD, 0xB1882D1D, 0x98B3389E, 0x593DE75E, 0xC0DF815F, 0x01515E9F,
|
||||
0x92A9AA59, 0x53277599, 0xCAC51398, 0x0B4BCC58, 0x2270D9DB, 0xE3FE061B, 0x7A1C601A,
|
||||
0xBB92BFDA, 0xD64819EF, 0x17C6C62F, 0x8E24A02E, 0x4FAA7FEE, 0x66916A6D, 0xA71FB5AD,
|
||||
0x3EFDD3AC, 0xFF730C6C, 0x6C8BF8AA, 0xAD05276A, 0x34E7416B, 0xF5699EAB, 0xDC528B28,
|
||||
0x1DDC54E8, 0x843E32E9, 0x45B0ED29, 0x78BEDD24, 0xB93002E4, 0x20D264E5, 0xE15CBB25,
|
||||
0xC867AEA6, 0x09E97166, 0x900B1767, 0x5185C8A7, 0xC27D3C61, 0x03F3E3A1, 0x9A1185A0,
|
||||
0x5B9F5A60, 0x72A44FE3, 0xB32A9023, 0x2AC8F622, 0xEB4629E2, 0x50D49638, 0x915A49F8,
|
||||
0x08B82FF9, 0xC936F039, 0xE00DE5BA, 0x21833A7A, 0xB8615C7B, 0x79EF83BB, 0xEA17777D,
|
||||
0x2B99A8BD, 0xB27BCEBC, 0x73F5117C, 0x5ACE04FF, 0x9B40DB3F, 0x02A2BD3E, 0xC32C62FE,
|
||||
0xFE2252F3, 0x3FAC8D33, 0xA64EEB32, 0x67C034F2, 0x4EFB2171, 0x8F75FEB1, 0x169798B0,
|
||||
0xD7194770, 0x44E1B3B6, 0x856F6C76, 0x1C8D0A77, 0xDD03D5B7, 0xF438C034, 0x35B61FF4,
|
||||
0xAC5479F5, 0x6DDAA635, 0x77E1359F, 0xB66FEA5F, 0x2F8D8C5E, 0xEE03539E, 0xC738461D,
|
||||
0x06B699DD, 0x9F54FFDC, 0x5EDA201C, 0xCD22D4DA, 0x0CAC0B1A, 0x954E6D1B, 0x54C0B2DB,
|
||||
0x7DFBA758, 0xBC757898, 0x25971E99, 0xE419C159, 0xD917F154, 0x18992E94, 0x817B4895,
|
||||
0x40F59755, 0x69CE82D6, 0xA8405D16, 0x31A23B17, 0xF02CE4D7, 0x63D41011, 0xA25ACFD1,
|
||||
0x3BB8A9D0, 0xFA367610, 0xD30D6393, 0x1283BC53, 0x8B61DA52, 0x4AEF0592, 0xF17DBA48,
|
||||
0x30F36588, 0xA9110389, 0x689FDC49, 0x41A4C9CA, 0x802A160A, 0x19C8700B, 0xD846AFCB,
|
||||
0x4BBE5B0D, 0x8A3084CD, 0x13D2E2CC, 0xD25C3D0C, 0xFB67288F, 0x3AE9F74F, 0xA30B914E,
|
||||
0x62854E8E, 0x5F8B7E83, 0x9E05A143, 0x07E7C742, 0xC6691882, 0xEF520D01, 0x2EDCD2C1,
|
||||
0xB73EB4C0, 0x76B06B00, 0xE5489FC6, 0x24C64006, 0xBD242607, 0x7CAAF9C7, 0x5591EC44,
|
||||
0x941F3384, 0x0DFD5585, 0xCC738A45, 0xA1A92C70, 0x6027F3B0, 0xF9C595B1, 0x384B4A71,
|
||||
0x11705FF2, 0xD0FE8032, 0x491CE633, 0x889239F3, 0x1B6ACD35, 0xDAE412F5, 0x430674F4,
|
||||
0x8288AB34, 0xABB3BEB7, 0x6A3D6177, 0xF3DF0776, 0x3251D8B6, 0x0F5FE8BB, 0xCED1377B,
|
||||
0x5733517A, 0x96BD8EBA, 0xBF869B39, 0x7E0844F9, 0xE7EA22F8, 0x2664FD38, 0xB59C09FE,
|
||||
0x7412D63E, 0xEDF0B03F, 0x2C7E6FFF, 0x05457A7C, 0xC4CBA5BC, 0x5D29C3BD, 0x9CA71C7D,
|
||||
0x2735A3A7, 0xE6BB7C67, 0x7F591A66, 0xBED7C5A6, 0x97ECD025, 0x56620FE5, 0xCF8069E4,
|
||||
0x0E0EB624, 0x9DF642E2, 0x5C789D22, 0xC59AFB23, 0x041424E3, 0x2D2F3160, 0xECA1EEA0,
|
||||
0x754388A1, 0xB4CD5761, 0x89C3676C, 0x484DB8AC, 0xD1AFDEAD, 0x1021016D, 0x391A14EE,
|
||||
0xF894CB2E, 0x6176AD2F, 0xA0F872EF, 0x33008629, 0xF28E59E9, 0x6B6C3FE8, 0xAAE2E028,
|
||||
0x83D9F5AB, 0x42572A6B, 0xDBB54C6A, 0x1A3B93AA,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x9BA54C6F, 0xEC3B9E9F, 0x779ED2F0, 0x03063B7F, 0x98A37710, 0xEF3DA5E0,
|
||||
0x7498E98F, 0x060C76FE, 0x9DA93A91, 0xEA37E861, 0x7192A40E, 0x050A4D81, 0x9EAF01EE,
|
||||
0xE931D31E, 0x72949F71, 0x0C18EDFC, 0x97BDA193, 0xE0237363, 0x7B863F0C, 0x0F1ED683,
|
||||
0x94BB9AEC, 0xE325481C, 0x78800473, 0x0A149B02, 0x91B1D76D, 0xE62F059D, 0x7D8A49F2,
|
||||
0x0912A07D, 0x92B7EC12, 0xE5293EE2, 0x7E8C728D, 0x1831DBF8, 0x83949797, 0xF40A4567,
|
||||
0x6FAF0908, 0x1B37E087, 0x8092ACE8, 0xF70C7E18, 0x6CA93277, 0x1E3DAD06, 0x8598E169,
|
||||
0xF2063399, 0x69A37FF6, 0x1D3B9679, 0x869EDA16, 0xF10008E6, 0x6AA54489, 0x14293604,
|
||||
0x8F8C7A6B, 0xF812A89B, 0x63B7E4F4, 0x172F0D7B, 0x8C8A4114, 0xFB1493E4, 0x60B1DF8B,
|
||||
0x122540FA, 0x89800C95, 0xFE1EDE65, 0x65BB920A, 0x11237B85, 0x8A8637EA, 0xFD18E51A,
|
||||
0x66BDA975, 0x3063B7F0, 0xABC6FB9F, 0xDC58296F, 0x47FD6500, 0x33658C8F, 0xA8C0C0E0,
|
||||
0xDF5E1210, 0x44FB5E7F, 0x366FC10E, 0xADCA8D61, 0xDA545F91, 0x41F113FE, 0x3569FA71,
|
||||
0xAECCB61E, 0xD95264EE, 0x42F72881, 0x3C7B5A0C, 0xA7DE1663, 0xD040C493, 0x4BE588FC,
|
||||
0x3F7D6173, 0xA4D82D1C, 0xD346FFEC, 0x48E3B383, 0x3A772CF2, 0xA1D2609D, 0xD64CB26D,
|
||||
0x4DE9FE02, 0x3971178D, 0xA2D45BE2, 0xD54A8912, 0x4EEFC57D, 0x28526C08, 0xB3F72067,
|
||||
0xC469F297, 0x5FCCBEF8, 0x2B545777, 0xB0F11B18, 0xC76FC9E8, 0x5CCA8587, 0x2E5E1AF6,
|
||||
0xB5FB5699, 0xC2658469, 0x59C0C806, 0x2D582189, 0xB6FD6DE6, 0xC163BF16, 0x5AC6F379,
|
||||
0x244A81F4, 0xBFEFCD9B, 0xC8711F6B, 0x53D45304, 0x274CBA8B, 0xBCE9F6E4, 0xCB772414,
|
||||
0x50D2687B, 0x2246F70A, 0xB9E3BB65, 0xCE7D6995, 0x55D825FA, 0x2140CC75, 0xBAE5801A,
|
||||
0xCD7B52EA, 0x56DE1E85, 0x60C76FE0, 0xFB62238F, 0x8CFCF17F, 0x1759BD10, 0x63C1549F,
|
||||
0xF86418F0, 0x8FFACA00, 0x145F866F, 0x66CB191E, 0xFD6E5571, 0x8AF08781, 0x1155CBEE,
|
||||
0x65CD2261, 0xFE686E0E, 0x89F6BCFE, 0x1253F091, 0x6CDF821C, 0xF77ACE73, 0x80E41C83,
|
||||
0x1B4150EC, 0x6FD9B963, 0xF47CF50C, 0x83E227FC, 0x18476B93, 0x6AD3F4E2, 0xF176B88D,
|
||||
0x86E86A7D, 0x1D4D2612, 0x69D5CF9D, 0xF27083F2, 0x85EE5102, 0x1E4B1D6D, 0x78F6B418,
|
||||
0xE353F877, 0x94CD2A87, 0x0F6866E8, 0x7BF08F67, 0xE055C308, 0x97CB11F8, 0x0C6E5D97,
|
||||
0x7EFAC2E6, 0xE55F8E89, 0x92C15C79, 0x09641016, 0x7DFCF999, 0xE659B5F6, 0x91C76706,
|
||||
0x0A622B69, 0x74EE59E4, 0xEF4B158B, 0x98D5C77B, 0x03708B14, 0x77E8629B, 0xEC4D2EF4,
|
||||
0x9BD3FC04, 0x0076B06B, 0x72E22F1A, 0xE9476375, 0x9ED9B185, 0x057CFDEA, 0x71E41465,
|
||||
0xEA41580A, 0x9DDF8AFA, 0x067AC695, 0x50A4D810, 0xCB01947F, 0xBC9F468F, 0x273A0AE0,
|
||||
0x53A2E36F, 0xC807AF00, 0xBF997DF0, 0x243C319F, 0x56A8AEEE, 0xCD0DE281, 0xBA933071,
|
||||
0x21367C1E, 0x55AE9591, 0xCE0BD9FE, 0xB9950B0E, 0x22304761, 0x5CBC35EC, 0xC7197983,
|
||||
0xB087AB73, 0x2B22E71C, 0x5FBA0E93, 0xC41F42FC, 0xB381900C, 0x2824DC63, 0x5AB04312,
|
||||
0xC1150F7D, 0xB68BDD8D, 0x2D2E91E2, 0x59B6786D, 0xC2133402, 0xB58DE6F2, 0x2E28AA9D,
|
||||
0x489503E8, 0xD3304F87, 0xA4AE9D77, 0x3F0BD118, 0x4B933897, 0xD03674F8, 0xA7A8A608,
|
||||
0x3C0DEA67, 0x4E997516, 0xD53C3979, 0xA2A2EB89, 0x3907A7E6, 0x4D9F4E69, 0xD63A0206,
|
||||
0xA1A4D0F6, 0x3A019C99, 0x448DEE14, 0xDF28A27B, 0xA8B6708B, 0x33133CE4, 0x478BD56B,
|
||||
0xDC2E9904, 0xABB04BF4, 0x3015079B, 0x428198EA, 0xD924D485, 0xAEBA0675, 0x351F4A1A,
|
||||
0x4187A395, 0xDA22EFFA, 0xADBC3D0A, 0x36197165,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xDD96D985, 0x605CB54B, 0xBDCA6CCE, 0xC0B96A96, 0x1D2FB313, 0xA0E5DFDD,
|
||||
0x7D730658, 0x5A03D36D, 0x87950AE8, 0x3A5F6626, 0xE7C9BFA3, 0x9ABAB9FB, 0x472C607E,
|
||||
0xFAE60CB0, 0x2770D535, 0xB407A6DA, 0x69917F5F, 0xD45B1391, 0x09CDCA14, 0x74BECC4C,
|
||||
0xA92815C9, 0x14E27907, 0xC974A082, 0xEE0475B7, 0x3392AC32, 0x8E58C0FC, 0x53CE1979,
|
||||
0x2EBD1F21, 0xF32BC6A4, 0x4EE1AA6A, 0x937773EF, 0xB37E4BF5, 0x6EE89270, 0xD322FEBE,
|
||||
0x0EB4273B, 0x73C72163, 0xAE51F8E6, 0x139B9428, 0xCE0D4DAD, 0xE97D9898, 0x34EB411D,
|
||||
0x89212DD3, 0x54B7F456, 0x29C4F20E, 0xF4522B8B, 0x49984745, 0x940E9EC0, 0x0779ED2F,
|
||||
0xDAEF34AA, 0x67255864, 0xBAB381E1, 0xC7C087B9, 0x1A565E3C, 0xA79C32F2, 0x7A0AEB77,
|
||||
0x5D7A3E42, 0x80ECE7C7, 0x3D268B09, 0xE0B0528C, 0x9DC354D4, 0x40558D51, 0xFD9FE19F,
|
||||
0x2009381A, 0xBD8D91AB, 0x601B482E, 0xDDD124E0, 0x0047FD65, 0x7D34FB3D, 0xA0A222B8,
|
||||
0x1D684E76, 0xC0FE97F3, 0xE78E42C6, 0x3A189B43, 0x87D2F78D, 0x5A442E08, 0x27372850,
|
||||
0xFAA1F1D5, 0x476B9D1B, 0x9AFD449E, 0x098A3771, 0xD41CEEF4, 0x69D6823A, 0xB4405BBF,
|
||||
0xC9335DE7, 0x14A58462, 0xA96FE8AC, 0x74F93129, 0x5389E41C, 0x8E1F3D99, 0x33D55157,
|
||||
0xEE4388D2, 0x93308E8A, 0x4EA6570F, 0xF36C3BC1, 0x2EFAE244, 0x0EF3DA5E, 0xD36503DB,
|
||||
0x6EAF6F15, 0xB339B690, 0xCE4AB0C8, 0x13DC694D, 0xAE160583, 0x7380DC06, 0x54F00933,
|
||||
0x8966D0B6, 0x34ACBC78, 0xE93A65FD, 0x944963A5, 0x49DFBA20, 0xF415D6EE, 0x29830F6B,
|
||||
0xBAF47C84, 0x6762A501, 0xDAA8C9CF, 0x073E104A, 0x7A4D1612, 0xA7DBCF97, 0x1A11A359,
|
||||
0xC7877ADC, 0xE0F7AFE9, 0x3D61766C, 0x80AB1AA2, 0x5D3DC327, 0x204EC57F, 0xFDD81CFA,
|
||||
0x40127034, 0x9D84A9B1, 0xA06A2517, 0x7DFCFC92, 0xC036905C, 0x1DA049D9, 0x60D34F81,
|
||||
0xBD459604, 0x008FFACA, 0xDD19234F, 0xFA69F67A, 0x27FF2FFF, 0x9A354331, 0x47A39AB4,
|
||||
0x3AD09CEC, 0xE7464569, 0x5A8C29A7, 0x871AF022, 0x146D83CD, 0xC9FB5A48, 0x74313686,
|
||||
0xA9A7EF03, 0xD4D4E95B, 0x094230DE, 0xB4885C10, 0x691E8595, 0x4E6E50A0, 0x93F88925,
|
||||
0x2E32E5EB, 0xF3A43C6E, 0x8ED73A36, 0x5341E3B3, 0xEE8B8F7D, 0x331D56F8, 0x13146EE2,
|
||||
0xCE82B767, 0x7348DBA9, 0xAEDE022C, 0xD3AD0474, 0x0E3BDDF1, 0xB3F1B13F, 0x6E6768BA,
|
||||
0x4917BD8F, 0x9481640A, 0x294B08C4, 0xF4DDD141, 0x89AED719, 0x54380E9C, 0xE9F26252,
|
||||
0x3464BBD7, 0xA713C838, 0x7A8511BD, 0xC74F7D73, 0x1AD9A4F6, 0x67AAA2AE, 0xBA3C7B2B,
|
||||
0x07F617E5, 0xDA60CE60, 0xFD101B55, 0x2086C2D0, 0x9D4CAE1E, 0x40DA779B, 0x3DA971C3,
|
||||
0xE03FA846, 0x5DF5C488, 0x80631D0D, 0x1DE7B4BC, 0xC0716D39, 0x7DBB01F7, 0xA02DD872,
|
||||
0xDD5EDE2A, 0x00C807AF, 0xBD026B61, 0x6094B2E4, 0x47E467D1, 0x9A72BE54, 0x27B8D29A,
|
||||
0xFA2E0B1F, 0x875D0D47, 0x5ACBD4C2, 0xE701B80C, 0x3A976189, 0xA9E01266, 0x7476CBE3,
|
||||
0xC9BCA72D, 0x142A7EA8, 0x695978F0, 0xB4CFA175, 0x0905CDBB, 0xD493143E, 0xF3E3C10B,
|
||||
0x2E75188E, 0x93BF7440, 0x4E29ADC5, 0x335AAB9D, 0xEECC7218, 0x53061ED6, 0x8E90C753,
|
||||
0xAE99FF49, 0x730F26CC, 0xCEC54A02, 0x13539387, 0x6E2095DF, 0xB3B64C5A, 0x0E7C2094,
|
||||
0xD3EAF911, 0xF49A2C24, 0x290CF5A1, 0x94C6996F, 0x495040EA, 0x342346B2, 0xE9B59F37,
|
||||
0x547FF3F9, 0x89E92A7C, 0x1A9E5993, 0xC7088016, 0x7AC2ECD8, 0xA754355D, 0xDA273305,
|
||||
0x07B1EA80, 0xBA7B864E, 0x67ED5FCB, 0x409D8AFE, 0x9D0B537B, 0x20C13FB5, 0xFD57E630,
|
||||
0x8024E068, 0x5DB239ED, 0xE0785523, 0x3DEE8CA6,
|
||||
],
|
||||
[
|
||||
0x00000000, 0x9D0FE176, 0xE16EC4AD, 0x7C6125DB, 0x19AC8F1B, 0x84A36E6D, 0xF8C24BB6,
|
||||
0x65CDAAC0, 0x33591E36, 0xAE56FF40, 0xD237DA9B, 0x4F383BED, 0x2AF5912D, 0xB7FA705B,
|
||||
0xCB9B5580, 0x5694B4F6, 0x66B23C6C, 0xFBBDDD1A, 0x87DCF8C1, 0x1AD319B7, 0x7F1EB377,
|
||||
0xE2115201, 0x9E7077DA, 0x037F96AC, 0x55EB225A, 0xC8E4C32C, 0xB485E6F7, 0x298A0781,
|
||||
0x4C47AD41, 0xD1484C37, 0xAD2969EC, 0x3026889A, 0xCD6478D8, 0x506B99AE, 0x2C0ABC75,
|
||||
0xB1055D03, 0xD4C8F7C3, 0x49C716B5, 0x35A6336E, 0xA8A9D218, 0xFE3D66EE, 0x63328798,
|
||||
0x1F53A243, 0x825C4335, 0xE791E9F5, 0x7A9E0883, 0x06FF2D58, 0x9BF0CC2E, 0xABD644B4,
|
||||
0x36D9A5C2, 0x4AB88019, 0xD7B7616F, 0xB27ACBAF, 0x2F752AD9, 0x53140F02, 0xCE1BEE74,
|
||||
0x988F5A82, 0x0580BBF4, 0x79E19E2F, 0xE4EE7F59, 0x8123D599, 0x1C2C34EF, 0x604D1134,
|
||||
0xFD42F042, 0x41B9F7F1, 0xDCB61687, 0xA0D7335C, 0x3DD8D22A, 0x581578EA, 0xC51A999C,
|
||||
0xB97BBC47, 0x24745D31, 0x72E0E9C7, 0xEFEF08B1, 0x938E2D6A, 0x0E81CC1C, 0x6B4C66DC,
|
||||
0xF64387AA, 0x8A22A271, 0x172D4307, 0x270BCB9D, 0xBA042AEB, 0xC6650F30, 0x5B6AEE46,
|
||||
0x3EA74486, 0xA3A8A5F0, 0xDFC9802B, 0x42C6615D, 0x1452D5AB, 0x895D34DD, 0xF53C1106,
|
||||
0x6833F070, 0x0DFE5AB0, 0x90F1BBC6, 0xEC909E1D, 0x719F7F6B, 0x8CDD8F29, 0x11D26E5F,
|
||||
0x6DB34B84, 0xF0BCAAF2, 0x95710032, 0x087EE144, 0x741FC49F, 0xE91025E9, 0xBF84911F,
|
||||
0x228B7069, 0x5EEA55B2, 0xC3E5B4C4, 0xA6281E04, 0x3B27FF72, 0x4746DAA9, 0xDA493BDF,
|
||||
0xEA6FB345, 0x77605233, 0x0B0177E8, 0x960E969E, 0xF3C33C5E, 0x6ECCDD28, 0x12ADF8F3,
|
||||
0x8FA21985, 0xD936AD73, 0x44394C05, 0x385869DE, 0xA55788A8, 0xC09A2268, 0x5D95C31E,
|
||||
0x21F4E6C5, 0xBCFB07B3, 0x8373EFE2, 0x1E7C0E94, 0x621D2B4F, 0xFF12CA39, 0x9ADF60F9,
|
||||
0x07D0818F, 0x7BB1A454, 0xE6BE4522, 0xB02AF1D4, 0x2D2510A2, 0x51443579, 0xCC4BD40F,
|
||||
0xA9867ECF, 0x34899FB9, 0x48E8BA62, 0xD5E75B14, 0xE5C1D38E, 0x78CE32F8, 0x04AF1723,
|
||||
0x99A0F655, 0xFC6D5C95, 0x6162BDE3, 0x1D039838, 0x800C794E, 0xD698CDB8, 0x4B972CCE,
|
||||
0x37F60915, 0xAAF9E863, 0xCF3442A3, 0x523BA3D5, 0x2E5A860E, 0xB3556778, 0x4E17973A,
|
||||
0xD318764C, 0xAF795397, 0x3276B2E1, 0x57BB1821, 0xCAB4F957, 0xB6D5DC8C, 0x2BDA3DFA,
|
||||
0x7D4E890C, 0xE041687A, 0x9C204DA1, 0x012FACD7, 0x64E20617, 0xF9EDE761, 0x858CC2BA,
|
||||
0x188323CC, 0x28A5AB56, 0xB5AA4A20, 0xC9CB6FFB, 0x54C48E8D, 0x3109244D, 0xAC06C53B,
|
||||
0xD067E0E0, 0x4D680196, 0x1BFCB560, 0x86F35416, 0xFA9271CD, 0x679D90BB, 0x02503A7B,
|
||||
0x9F5FDB0D, 0xE33EFED6, 0x7E311FA0, 0xC2CA1813, 0x5FC5F965, 0x23A4DCBE, 0xBEAB3DC8,
|
||||
0xDB669708, 0x4669767E, 0x3A0853A5, 0xA707B2D3, 0xF1930625, 0x6C9CE753, 0x10FDC288,
|
||||
0x8DF223FE, 0xE83F893E, 0x75306848, 0x09514D93, 0x945EACE5, 0xA478247F, 0x3977C509,
|
||||
0x4516E0D2, 0xD81901A4, 0xBDD4AB64, 0x20DB4A12, 0x5CBA6FC9, 0xC1B58EBF, 0x97213A49,
|
||||
0x0A2EDB3F, 0x764FFEE4, 0xEB401F92, 0x8E8DB552, 0x13825424, 0x6FE371FF, 0xF2EC9089,
|
||||
0x0FAE60CB, 0x92A181BD, 0xEEC0A466, 0x73CF4510, 0x1602EFD0, 0x8B0D0EA6, 0xF76C2B7D,
|
||||
0x6A63CA0B, 0x3CF77EFD, 0xA1F89F8B, 0xDD99BA50, 0x40965B26, 0x255BF1E6, 0xB8541090,
|
||||
0xC435354B, 0x593AD43D, 0x691C5CA7, 0xF413BDD1, 0x8872980A, 0x157D797C, 0x70B0D3BC,
|
||||
0xEDBF32CA, 0x91DE1711, 0x0CD1F667, 0x5A454291, 0xC74AA3E7, 0xBB2B863C, 0x2624674A,
|
||||
0x43E9CD8A, 0xDEE62CFC, 0xA2870927, 0x3F88E851,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xB9FBDBE8, 0xA886B191, 0x117D6A79, 0x8A7C6563, 0x3387BE8B, 0x22FAD4F2,
|
||||
0x9B010F1A, 0xCF89CC87, 0x7672176F, 0x670F7D16, 0xDEF4A6FE, 0x45F5A9E4, 0xFC0E720C,
|
||||
0xED731875, 0x5488C39D, 0x44629F4F, 0xFD9944A7, 0xECE42EDE, 0x551FF536, 0xCE1EFA2C,
|
||||
0x77E521C4, 0x66984BBD, 0xDF639055, 0x8BEB53C8, 0x32108820, 0x236DE259, 0x9A9639B1,
|
||||
0x019736AB, 0xB86CED43, 0xA911873A, 0x10EA5CD2, 0x88C53E9E, 0x313EE576, 0x20438F0F,
|
||||
0x99B854E7, 0x02B95BFD, 0xBB428015, 0xAA3FEA6C, 0x13C43184, 0x474CF219, 0xFEB729F1,
|
||||
0xEFCA4388, 0x56319860, 0xCD30977A, 0x74CB4C92, 0x65B626EB, 0xDC4DFD03, 0xCCA7A1D1,
|
||||
0x755C7A39, 0x64211040, 0xDDDACBA8, 0x46DBC4B2, 0xFF201F5A, 0xEE5D7523, 0x57A6AECB,
|
||||
0x032E6D56, 0xBAD5B6BE, 0xABA8DCC7, 0x1253072F, 0x89520835, 0x30A9D3DD, 0x21D4B9A4,
|
||||
0x982F624C, 0xCAFB7B7D, 0x7300A095, 0x627DCAEC, 0xDB861104, 0x40871E1E, 0xF97CC5F6,
|
||||
0xE801AF8F, 0x51FA7467, 0x0572B7FA, 0xBC896C12, 0xADF4066B, 0x140FDD83, 0x8F0ED299,
|
||||
0x36F50971, 0x27886308, 0x9E73B8E0, 0x8E99E432, 0x37623FDA, 0x261F55A3, 0x9FE48E4B,
|
||||
0x04E58151, 0xBD1E5AB9, 0xAC6330C0, 0x1598EB28, 0x411028B5, 0xF8EBF35D, 0xE9969924,
|
||||
0x506D42CC, 0xCB6C4DD6, 0x7297963E, 0x63EAFC47, 0xDA1127AF, 0x423E45E3, 0xFBC59E0B,
|
||||
0xEAB8F472, 0x53432F9A, 0xC8422080, 0x71B9FB68, 0x60C49111, 0xD93F4AF9, 0x8DB78964,
|
||||
0x344C528C, 0x253138F5, 0x9CCAE31D, 0x07CBEC07, 0xBE3037EF, 0xAF4D5D96, 0x16B6867E,
|
||||
0x065CDAAC, 0xBFA70144, 0xAEDA6B3D, 0x1721B0D5, 0x8C20BFCF, 0x35DB6427, 0x24A60E5E,
|
||||
0x9D5DD5B6, 0xC9D5162B, 0x702ECDC3, 0x6153A7BA, 0xD8A87C52, 0x43A97348, 0xFA52A8A0,
|
||||
0xEB2FC2D9, 0x52D41931, 0x4E87F0BB, 0xF77C2B53, 0xE601412A, 0x5FFA9AC2, 0xC4FB95D8,
|
||||
0x7D004E30, 0x6C7D2449, 0xD586FFA1, 0x810E3C3C, 0x38F5E7D4, 0x29888DAD, 0x90735645,
|
||||
0x0B72595F, 0xB28982B7, 0xA3F4E8CE, 0x1A0F3326, 0x0AE56FF4, 0xB31EB41C, 0xA263DE65,
|
||||
0x1B98058D, 0x80990A97, 0x3962D17F, 0x281FBB06, 0x91E460EE, 0xC56CA373, 0x7C97789B,
|
||||
0x6DEA12E2, 0xD411C90A, 0x4F10C610, 0xF6EB1DF8, 0xE7967781, 0x5E6DAC69, 0xC642CE25,
|
||||
0x7FB915CD, 0x6EC47FB4, 0xD73FA45C, 0x4C3EAB46, 0xF5C570AE, 0xE4B81AD7, 0x5D43C13F,
|
||||
0x09CB02A2, 0xB030D94A, 0xA14DB333, 0x18B668DB, 0x83B767C1, 0x3A4CBC29, 0x2B31D650,
|
||||
0x92CA0DB8, 0x8220516A, 0x3BDB8A82, 0x2AA6E0FB, 0x935D3B13, 0x085C3409, 0xB1A7EFE1,
|
||||
0xA0DA8598, 0x19215E70, 0x4DA99DED, 0xF4524605, 0xE52F2C7C, 0x5CD4F794, 0xC7D5F88E,
|
||||
0x7E2E2366, 0x6F53491F, 0xD6A892F7, 0x847C8BC6, 0x3D87502E, 0x2CFA3A57, 0x9501E1BF,
|
||||
0x0E00EEA5, 0xB7FB354D, 0xA6865F34, 0x1F7D84DC, 0x4BF54741, 0xF20E9CA9, 0xE373F6D0,
|
||||
0x5A882D38, 0xC1892222, 0x7872F9CA, 0x690F93B3, 0xD0F4485B, 0xC01E1489, 0x79E5CF61,
|
||||
0x6898A518, 0xD1637EF0, 0x4A6271EA, 0xF399AA02, 0xE2E4C07B, 0x5B1F1B93, 0x0F97D80E,
|
||||
0xB66C03E6, 0xA711699F, 0x1EEAB277, 0x85EBBD6D, 0x3C106685, 0x2D6D0CFC, 0x9496D714,
|
||||
0x0CB9B558, 0xB5426EB0, 0xA43F04C9, 0x1DC4DF21, 0x86C5D03B, 0x3F3E0BD3, 0x2E4361AA,
|
||||
0x97B8BA42, 0xC33079DF, 0x7ACBA237, 0x6BB6C84E, 0xD24D13A6, 0x494C1CBC, 0xF0B7C754,
|
||||
0xE1CAAD2D, 0x583176C5, 0x48DB2A17, 0xF120F1FF, 0xE05D9B86, 0x59A6406E, 0xC2A74F74,
|
||||
0x7B5C949C, 0x6A21FEE5, 0xD3DA250D, 0x8752E690, 0x3EA93D78, 0x2FD45701, 0x962F8CE9,
|
||||
0x0D2E83F3, 0xB4D5581B, 0xA5A83262, 0x1C53E98A,
|
||||
],
|
||||
[
|
||||
0x00000000, 0xAE689191, 0x87A02563, 0x29C8B4F2, 0xD4314C87, 0x7A59DD16, 0x539169E4,
|
||||
0xFDF9F875, 0x73139F4F, 0xDD7B0EDE, 0xF4B3BA2C, 0x5ADB2BBD, 0xA722D3C8, 0x094A4259,
|
||||
0x2082F6AB, 0x8EEA673A, 0xE6273E9E, 0x484FAF0F, 0x61871BFD, 0xCFEF8A6C, 0x32167219,
|
||||
0x9C7EE388, 0xB5B6577A, 0x1BDEC6EB, 0x9534A1D1, 0x3B5C3040, 0x129484B2, 0xBCFC1523,
|
||||
0x4105ED56, 0xEF6D7CC7, 0xC6A5C835, 0x68CD59A4, 0x173F7B7D, 0xB957EAEC, 0x909F5E1E,
|
||||
0x3EF7CF8F, 0xC30E37FA, 0x6D66A66B, 0x44AE1299, 0xEAC68308, 0x642CE432, 0xCA4475A3,
|
||||
0xE38CC151, 0x4DE450C0, 0xB01DA8B5, 0x1E753924, 0x37BD8DD6, 0x99D51C47, 0xF11845E3,
|
||||
0x5F70D472, 0x76B86080, 0xD8D0F111, 0x25290964, 0x8B4198F5, 0xA2892C07, 0x0CE1BD96,
|
||||
0x820BDAAC, 0x2C634B3D, 0x05ABFFCF, 0xABC36E5E, 0x563A962B, 0xF85207BA, 0xD19AB348,
|
||||
0x7FF222D9, 0x2E7EF6FA, 0x8016676B, 0xA9DED399, 0x07B64208, 0xFA4FBA7D, 0x54272BEC,
|
||||
0x7DEF9F1E, 0xD3870E8F, 0x5D6D69B5, 0xF305F824, 0xDACD4CD6, 0x74A5DD47, 0x895C2532,
|
||||
0x2734B4A3, 0x0EFC0051, 0xA09491C0, 0xC859C864, 0x663159F5, 0x4FF9ED07, 0xE1917C96,
|
||||
0x1C6884E3, 0xB2001572, 0x9BC8A180, 0x35A03011, 0xBB4A572B, 0x1522C6BA, 0x3CEA7248,
|
||||
0x9282E3D9, 0x6F7B1BAC, 0xC1138A3D, 0xE8DB3ECF, 0x46B3AF5E, 0x39418D87, 0x97291C16,
|
||||
0xBEE1A8E4, 0x10893975, 0xED70C100, 0x43185091, 0x6AD0E463, 0xC4B875F2, 0x4A5212C8,
|
||||
0xE43A8359, 0xCDF237AB, 0x639AA63A, 0x9E635E4F, 0x300BCFDE, 0x19C37B2C, 0xB7ABEABD,
|
||||
0xDF66B319, 0x710E2288, 0x58C6967A, 0xF6AE07EB, 0x0B57FF9E, 0xA53F6E0F, 0x8CF7DAFD,
|
||||
0x229F4B6C, 0xAC752C56, 0x021DBDC7, 0x2BD50935, 0x85BD98A4, 0x784460D1, 0xD62CF140,
|
||||
0xFFE445B2, 0x518CD423, 0x5CFDEDF4, 0xF2957C65, 0xDB5DC897, 0x75355906, 0x88CCA173,
|
||||
0x26A430E2, 0x0F6C8410, 0xA1041581, 0x2FEE72BB, 0x8186E32A, 0xA84E57D8, 0x0626C649,
|
||||
0xFBDF3E3C, 0x55B7AFAD, 0x7C7F1B5F, 0xD2178ACE, 0xBADAD36A, 0x14B242FB, 0x3D7AF609,
|
||||
0x93126798, 0x6EEB9FED, 0xC0830E7C, 0xE94BBA8E, 0x47232B1F, 0xC9C94C25, 0x67A1DDB4,
|
||||
0x4E696946, 0xE001F8D7, 0x1DF800A2, 0xB3909133, 0x9A5825C1, 0x3430B450, 0x4BC29689,
|
||||
0xE5AA0718, 0xCC62B3EA, 0x620A227B, 0x9FF3DA0E, 0x319B4B9F, 0x1853FF6D, 0xB63B6EFC,
|
||||
0x38D109C6, 0x96B99857, 0xBF712CA5, 0x1119BD34, 0xECE04541, 0x4288D4D0, 0x6B406022,
|
||||
0xC528F1B3, 0xADE5A817, 0x038D3986, 0x2A458D74, 0x842D1CE5, 0x79D4E490, 0xD7BC7501,
|
||||
0xFE74C1F3, 0x501C5062, 0xDEF63758, 0x709EA6C9, 0x5956123B, 0xF73E83AA, 0x0AC77BDF,
|
||||
0xA4AFEA4E, 0x8D675EBC, 0x230FCF2D, 0x72831B0E, 0xDCEB8A9F, 0xF5233E6D, 0x5B4BAFFC,
|
||||
0xA6B25789, 0x08DAC618, 0x211272EA, 0x8F7AE37B, 0x01908441, 0xAFF815D0, 0x8630A122,
|
||||
0x285830B3, 0xD5A1C8C6, 0x7BC95957, 0x5201EDA5, 0xFC697C34, 0x94A42590, 0x3ACCB401,
|
||||
0x130400F3, 0xBD6C9162, 0x40956917, 0xEEFDF886, 0xC7354C74, 0x695DDDE5, 0xE7B7BADF,
|
||||
0x49DF2B4E, 0x60179FBC, 0xCE7F0E2D, 0x3386F658, 0x9DEE67C9, 0xB426D33B, 0x1A4E42AA,
|
||||
0x65BC6073, 0xCBD4F1E2, 0xE21C4510, 0x4C74D481, 0xB18D2CF4, 0x1FE5BD65, 0x362D0997,
|
||||
0x98459806, 0x16AFFF3C, 0xB8C76EAD, 0x910FDA5F, 0x3F674BCE, 0xC29EB3BB, 0x6CF6222A,
|
||||
0x453E96D8, 0xEB560749, 0x839B5EED, 0x2DF3CF7C, 0x043B7B8E, 0xAA53EA1F, 0x57AA126A,
|
||||
0xF9C283FB, 0xD00A3709, 0x7E62A698, 0xF088C1A2, 0x5EE05033, 0x7728E4C1, 0xD9407550,
|
||||
0x24B98D25, 0x8AD11CB4, 0xA319A846, 0x0D7139D7,
|
||||
],
|
||||
];
|
2
third_party/rust/image/.cargo-checksum.json
vendored
2
third_party/rust/image/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"CHANGES.md":"57cd46de14af5277954df2d56b141fb8fd7eff75a026e11805281c167df13013","Cargo.toml":"42a0083afb5bffbcfde1f58caac0c9afe9642784afff80fdc5eefc3657c8abb1","LICENSE":"c7766d2e29f88a4be81b6ac6216c62d2d0918c7d3f2fc98be6fecac8f6595e60","README.md":"387f486de9a191fde35fd2ed93390824dd3f6b86b4971071a229ab9c4c4b82fc","benches/encode_jpeg.rs":"614f7ff101d8737fec76db00520d86d7a30cc4e1482e30c0414bfac868373427","benches/load.rs":"b50384f027734a1b6df6612f56b70ba95978138eb0d3894a8b8dbe0748d984bd","docs/2019-04-23-memory-unsafety.md":"b59a9af84bdb5efa1bc1f33c8aa22ff42590701817fb03f55ca2dd50af91bb8d","release.sh":"70f8d6272ab65f5ca80ac95e6ceeeb5041f9c183c87a1fdac2b7f2d16e0827d4","src/animation.rs":"c4bcc97aac7d929162e7d1e782ef4e20f3df72a891893ac68d8cda3b7aa431b3","src/bmp/decoder.rs":"f1abbda7c984122d990e1509cbdd6b1d488a49845662dc74815587f7befb302a","src/bmp/encoder.rs":"60b0ad7f086eead46799d78dd10fc7f1a27c6385d6a6c4ee2afd533e6ad1418f","src/bmp/mod.rs":"7105812c5bc077c8619359b6201110feeccec20b01f29a8f84aaef02be9b87d4","src/buffer.rs":"2e5a7d983794e71068f065a801b5483106fcf51fd74487ddd0c3f76a97f49ea0","src/color.rs":"6dde85a7fbc44d536bf7648fe1172277c6e9e3fbcd514df9bd53f277a10f85db","src/dxt.rs":"e17eef3e9abf53e89abb3a62264fb830639f2a63e48098d54e6e052b00e57342","src/dynimage.rs":"a9f598bf40bec92230dd5226cee87685d55dbb0053a54593c7083d7a394139d1","src/flat.rs":"01fd4f5a777d1e292b6f2a6a25cbac0d40ab8317898097caa32b28ba27d9baaf","src/gif.rs":"99df3010c731b6ad6f6a77a63c3b6071a801f4e171bbe01717fa273212f4767e","src/hdr/hdr_decoder.rs":"3ec4b069be9bfb43a646d9f6f13586fed93b47ac70c7fdb51ec36ef4199ecbd3","src/hdr/hdr_encoder.rs":"ed0d1845b1414bcdec641f2e158a364c04b717d41662ef40adb63bd32762c56f","src/hdr/mod.rs":"72f33fe6479cf4ce87765715c896bf0374bd2f4e0f98f50a63e084c0ff313ea8","src/ico/decoder.rs":"e3ea1fb1ff41b8cff58dd260902e8061cf6b44ca8721a68f76dce6a66ea4be19","src/ico/encoder.rs":"be5c290922c2fa91a174e22a221fce7730a1696e31c8a6e7dd45950afd63c80d","src/ico/mod.rs":"d94e6878c79c97eb9d9f9f9f9fb479ec8ccc1c8e788030ebe3b045ed44c0be5c","src/image.rs":"508dead9a324042c5307362ed246865bf5436391369a2e13d0192bd4949ab894","src/imageops/affine.rs":"46835b6c6eee3542f893789927053399a8d173a69c38685a48bfa632bd417140","src/imageops/colorops.rs":"5bff8d20a280793d0510d2e04f47f81b6b2be13a363cefe18264db0e1e3f6554","src/imageops/mod.rs":"148553f9ed42f256b1c59f61686fe247e560e5253d64492813ad2670f39223af","src/imageops/sample.rs":"4de9f0ab52459d446fe289c3e962d577c9b7019f85fd3ffd325c76d634256675","src/jpeg/decoder.rs":"9a3aa05db5d652901428a64e912670443a5c98843695394795e173cfb4a13549","src/jpeg/encoder.rs":"6ec6f205dbbb869ed3858a1c2e82b468d1b9341243f23c81ffbdcfcd79debd07","src/jpeg/entropy.rs":"31856ebc9b8647552e3ebe50f6c0608dadb181e75f8ce502395e6a713c12ad25","src/jpeg/mod.rs":"14a2ee879f88d27aca68a59d6b29112c66e1d61eaf9cad80ff73beabe1c092fe","src/jpeg/transform.rs":"c28670debd1cb6576c190495c64fa30610a2c29db65a2d3be3f625439df87031","src/lib.rs":"46dd648fab4da71d963552769325b03f10a2202780e2d6a2e23dbbdd960acaa7","src/math/mod.rs":"36b79d81c9192a3ec1e6107762623e1e7572d50825472ab824ab5d7b199e9380","src/math/nq.rs":"c6d25ac0f19db5d75668e0448df3580ddf0028261eb81517cc8c0acfaa0616cd","src/math/utils.rs":"2ae7ac728c6831559da97ed31d133cad81b3b5fe64998829b5579f34330a548e","src/png.rs":"2d356edc8d70670b72e712decb7b3e79c019f7ff8ef681acd579bcb311780d4c","src/pnm/autobreak.rs":"811445935b9217232af805a9f5521c2471b4397b804c0a5a2a87bb3240fcee96","src/pnm/decoder.rs":"c171eaaebfcfe760ba54dd3d61e62546cb114357672319e15344f4b8b2d6e700","src/pnm/encoder.rs":"d0980927546841d604b4f8dee06bd433b6a99cef3a6cdd721e819228805d00f5","src/pnm/header.rs":"42cf54d491095a4c5af706f6d67904387239f50430b167a12da74e2513c35065","src/pnm/mod.rs":"addb907337e7ef24c47de251b46ccafc9ea1f6d34f4141e14cf6da2481740fb6","src/tga/decoder.rs":"f021616befc9edf5d8f2d4912e296d5bc4f954b1f68c9f51d2d01a4288ddcbec","src/tga/mod.rs":"0a8001c03350156fad3ed9aefb3b3fb2a9112414cce2a0b31070cb1859ef2548","src/tiff.rs":"60297f928ad4ad94b2b57bb1c0b5800de8af9549fae6090f82a15ac995ce40b7","src/traits.rs":"58a12b0ddd1d7386447693d682a1df771e29263daeb5c27ad8829462ef3d1423","src/utils/mod.rs":"b1a3573f429d5bbe4ef13128152808a47f0e91602331f63ea65638edb29d9ed8","src/webp/decoder.rs":"963cea7fe4732ca74e8fa06b8fe32192158917664d2f2f7fd61fb160f42e7daf","src/webp/mod.rs":"f06f5e78091f7a0913fb5cd74d4880a71754ac4f33ee34f502474154be0af27a","src/webp/transform.rs":"f4eb9230045bc5bc277f0bd686014646716c2ebcb126f7d51b9fac622076517a","src/webp/vp8.rs":"d4f82d581ff1f689f46db1e662654577d99ef7e436273d6b07b9004bd50b09a7"},"package":"293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116"}
|
||||
{"files":{"CHANGES.md":"c791f6ca0016110889db58e22a8a7a0f38fec9c1e4f5066c2367a7c240324dc6","Cargo.toml":"706b43137bd0e8115d6dce2bf140ecd658a7c1cacc7849c7d80583f890c79642","LICENSE":"c7766d2e29f88a4be81b6ac6216c62d2d0918c7d3f2fc98be6fecac8f6595e60","README.md":"ad289be7955af45c631d8f398fb0d6e22c5bf81bfc8ce2e46d6c67a5128b1e28","benches/README.md":"87b2ea4d1cea80c1e24fc18f1222a7ee1a38f5a92e98110bb84a4827fb997b62","benches/encode_jpeg.rs":"614f7ff101d8737fec76db00520d86d7a30cc4e1482e30c0414bfac868373427","benches/load.rs":"b50384f027734a1b6df6612f56b70ba95978138eb0d3894a8b8dbe0748d984bd","docs/2019-04-23-memory-unsafety.md":"b59a9af84bdb5efa1bc1f33c8aa22ff42590701817fb03f55ca2dd50af91bb8d","release.sh":"70f8d6272ab65f5ca80ac95e6ceeeb5041f9c183c87a1fdac2b7f2d16e0827d4","src/animation.rs":"9afe0c9ee5de50c35f075839ecde79ad8be95627c8efbe68b5a69028a4061908","src/bmp/decoder.rs":"6a6ae94414e9fcc874041c29922ce11d27f840a2281e905babc9d0c15859cb9f","src/bmp/encoder.rs":"f97c6e0dc9c9404bd5191821d30f08410416a5a7cf516682de83888f3052e828","src/bmp/mod.rs":"7105812c5bc077c8619359b6201110feeccec20b01f29a8f84aaef02be9b87d4","src/buffer.rs":"bfd76adf1770ec544d9aecba1990fca8cc32b31de9e4b78eb717f47b0f93a60c","src/color.rs":"d43f63f8e38a356cbc45677e4cfc7043bbd9b0904883ce4792ab0267fdc64179","src/dxt.rs":"c887e91615dadff094f1e1f1d746b85366f704581e384febddd98be983aabbee","src/dynimage.rs":"353e4238e64671a6dffafa32be38cfe90fadb05e3b8b88a4696b5cc532bad827","src/flat.rs":"3fed74ddb298336f36337f789d11934cf9aad25615133f3b5c21f59fc61b34f2","src/gif.rs":"96d258a24f87a039b1447d647945e41c1eeedbc3b6c631edc001962c65da722a","src/hdr/decoder.rs":"c9ca526389b6f045cf7a46af0aeb34f114ebf985ca271a6b30b5a2387382d121","src/hdr/encoder.rs":"0555eed8ea351ad73a9af349f990311d660f35f4f46719d01b88fad41942f2e8","src/hdr/mod.rs":"96eb63b7e43f117cb46b8ffe705b477426dde75881f2dea63cab29ffd820e01d","src/ico/decoder.rs":"07fccb6e968e6821cda9ef1e9af77c4fbf969030fdd76dab516eb67462dc321e","src/ico/encoder.rs":"941b226433b25399e51ed4b9204e896b4a1cad6552cbd44c60b2b6d97627e52c","src/ico/mod.rs":"d94e6878c79c97eb9d9f9f9f9fb479ec8ccc1c8e788030ebe3b045ed44c0be5c","src/image.rs":"70192ee57a9daff27041c25ef32f8f911d0e4d7e40751e361b3eac80ed989431","src/imageops/affine.rs":"74ecc183bd739eb3168122613d245dd939770b8328a5e9e0737f0c24640f49c6","src/imageops/colorops.rs":"cd58e6553f3da0790e1cb406e50da0400658843440bbb47d016daf1965018b7f","src/imageops/mod.rs":"3856c7917c2a3805f1aced1f499da6b121b4ccb08f2b7a66eda5592641c06c2e","src/imageops/sample.rs":"8d746c4cedec21e249dab3585bd61c0e475a88e0917fea9378c36d4afddeb9aa","src/jpeg/decoder.rs":"df206c5bae9c39fd34dc41d304e5dc29df0d581ba7ed47f8604c3b7a756573c3","src/jpeg/encoder.rs":"66c28cfc9abca2db71f76016934c533d2843b2dfc64a3cb92d23d5bec417702b","src/jpeg/entropy.rs":"31856ebc9b8647552e3ebe50f6c0608dadb181e75f8ce502395e6a713c12ad25","src/jpeg/mod.rs":"14a2ee879f88d27aca68a59d6b29112c66e1d61eaf9cad80ff73beabe1c092fe","src/jpeg/transform.rs":"c28670debd1cb6576c190495c64fa30610a2c29db65a2d3be3f625439df87031","src/lib.rs":"1d0073935d587f57c0485208bac5e37333e66838cf09699d0ea42afe3e2beac0","src/math/mod.rs":"36b79d81c9192a3ec1e6107762623e1e7572d50825472ab824ab5d7b199e9380","src/math/nq.rs":"a3fe77839826ca1d446f496f53e33d081a623a248c087f1a08b8afb1eca4bcda","src/math/utils.rs":"2ae7ac728c6831559da97ed31d133cad81b3b5fe64998829b5579f34330a548e","src/png.rs":"5ba453410ada2026bcf935426639b93356f6e4b7edd2b8acd6a42c5770955eb6","src/pnm/autobreak.rs":"811445935b9217232af805a9f5521c2471b4397b804c0a5a2a87bb3240fcee96","src/pnm/decoder.rs":"25ac23fc8e67ea42d479a103e3cda1b51a4421950be9ee2c11eeec17552081c8","src/pnm/encoder.rs":"c87dc870e15515ff9ffcd003310904f303ba416fef72352e2a314357c4cae96a","src/pnm/header.rs":"81a0cf72c3b113b490054f4f2201b448cbb1fed63fc1354e457a94294bf3761f","src/pnm/mod.rs":"74ec15ee6d92dec08e7d0870bf31ad3c30687b2c52f74abdeb4bf127f3afda23","src/tga/decoder.rs":"f05fa02aba31bc5b423644be31f1c8b874e6557b8db211bc837d07dcee455bca","src/tga/mod.rs":"0a8001c03350156fad3ed9aefb3b3fb2a9112414cce2a0b31070cb1859ef2548","src/tiff.rs":"5fb6019db0ffbbad6a2c2aa083dd31514917885a030cd9aed8e89322aac6ef5f","src/traits.rs":"58a12b0ddd1d7386447693d682a1df771e29263daeb5c27ad8829462ef3d1423","src/utils/mod.rs":"5a9d379f45d6d626d63e6839f93cd41ed33d67186b205fe3a574a956b52dc4e7","src/webp/decoder.rs":"82666a293692c3043e3bcf6ab988e470f6b2f9cedf0b6b1202bb974d4ebbeddc","src/webp/mod.rs":"f06f5e78091f7a0913fb5cd74d4880a71754ac4f33ee34f502474154be0af27a","src/webp/transform.rs":"9772d4a3172122200482e09d763e554f41d8de8ab629f94c10d64ccac038faa1","src/webp/vp8.rs":"2d1f4522ceb43d541462030b2125e637a9b63ccc0205af5cfbb2f60cc879433e"},"package":"663a975007e0b49903e2e8ac0db2c432c465855f2d65f17883ba1476e85f0b42"}
|
35
third_party/rust/image/CHANGES.md
vendored
35
third_party/rust/image/CHANGES.md
vendored
@ -8,6 +8,41 @@ Rust image aims to be a pure-Rust implementation of various popular image format
|
||||
|
||||
## Changes
|
||||
|
||||
### Version 0.22
|
||||
|
||||
- The required Rust version is now `1.34.2`.
|
||||
- Note the website and blog: [image-rs.org][1] and [blog.image-rs.org][2]
|
||||
- `PixelMut` now only on `ImageBuffer` and removed from `GenericImage`
|
||||
interface. Prefer iterating manually in the generic case.
|
||||
- Replaced an unsafe interface in the hdr decoder with a safe variant.
|
||||
- Support loading 2-bit BMP images
|
||||
- Add method to save an `ImageBuffer`/`DynamicImage` with specified format
|
||||
- Update tiff to `0.3` with a writer
|
||||
- Update png to `0.15`, fixes reading of interlaced sub-byte pixels
|
||||
- Always use custom struct for `ImageDecoder::Reader`
|
||||
- Added `apply_without_alpha` and `map_without_alpha` to `Pixel` trait
|
||||
- Pixel information now with associated constants instead of static methods
|
||||
- Changed color structs to tuple types with single component. Improves
|
||||
ergonomics of destructuring assignment and construction.
|
||||
- Add lifetime parameter on `ImageDecoder` trait.
|
||||
- Remove unecessary `'static` bounds on affine operations
|
||||
- Add function to retrieve image dimensions without loading full image
|
||||
- Allow different image types in overlay and replace
|
||||
- Iterators over rows of `ImageBuffer`, mutable variants
|
||||
|
||||
[1]: https://www.image-rs.org
|
||||
[2]: https://blog.image-rs.org
|
||||
|
||||
### Version 0.21.2
|
||||
|
||||
- Fixed a variety of crashes and opaque errors in webp
|
||||
- Updated the png limits to be less restrictive
|
||||
- Reworked even more `unsafe` operations into safe alternatives
|
||||
- Derived Debug on FilterType and Deref on Pixel
|
||||
- Removed a restriction on DXT to always require power of two dimensions
|
||||
- Change the encoding of RGBA in bmp using bitfields
|
||||
- Corrected various urls
|
||||
|
||||
### Version 0.21.1
|
||||
|
||||
- A fairly important bugfix backport
|
||||
|
17
third_party/rust/image/Cargo.toml
vendored
17
third_party/rust/image/Cargo.toml
vendored
@ -3,7 +3,7 @@
|
||||
# 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
|
||||
# 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
|
||||
@ -12,16 +12,16 @@
|
||||
|
||||
[package]
|
||||
name = "image"
|
||||
version = "0.21.1"
|
||||
version = "0.22.1"
|
||||
authors = ["ccgn", "bvssvni <bvssvni@gmail.com>", "nwin", "TyOverby <ty@pre-alpha.com>", "HeroicKatora", "Calum", "CensoredUsername <cens.username@gmail.com>", "fintelia <fintelia@gmail.com>"]
|
||||
exclude = ["src/png/testdata/*", "examples/*", "tests/*"]
|
||||
description = "Imaging library written in Rust. Provides basic filters and decoders for the most common image formats."
|
||||
homepage = "https://github.com/PistonDevelopers/image"
|
||||
homepage = "https://github.com/image-rs/image"
|
||||
documentation = "https://docs.rs/image"
|
||||
readme = "README.md"
|
||||
categories = ["multimedia::images", "multimedia::encoding"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/PistonDevelopers/image.git"
|
||||
repository = "https://github.com/image-rs/image.git"
|
||||
|
||||
[lib]
|
||||
name = "image"
|
||||
@ -52,7 +52,7 @@ default-features = false
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies.png]
|
||||
version = "0.14"
|
||||
version = "0.15"
|
||||
optional = true
|
||||
|
||||
[dependencies.scoped_threadpool]
|
||||
@ -60,10 +60,13 @@ version = "0.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.tiff]
|
||||
version = "0.2.0"
|
||||
version = "0.3.1"
|
||||
optional = true
|
||||
[dev-dependencies.crc32fast]
|
||||
version = "1.2.0"
|
||||
|
||||
[dev-dependencies.glob]
|
||||
version = "0.2.10"
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.num-complex]
|
||||
version = "0.2.0"
|
||||
|
52
third_party/rust/image/README.md
vendored
52
third_party/rust/image/README.md
vendored
@ -1,8 +1,8 @@
|
||||
# Image [![Build Status](https://travis-ci.org/PistonDevelopers/image.svg?branch=master)](https://travis-ci.org/PistonDevelopers/image)
|
||||
# Image [![crates.io](https://img.shields.io/crates/v/image.svg)](https://crates.io/crates/image) [![Build Status](https://travis-ci.org/image-rs/image.svg?branch=master)](https://travis-ci.org/image-rs/image) [![Gitter](https://badges.gitter.im/image-rs/image.svg)](https://gitter.im/image-rs/image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
Maintainers: @nwin, @ccgn
|
||||
|
||||
[How to contribute](https://github.com/PistonDevelopers/piston/blob/master/CONTRIBUTING.md)
|
||||
[How to contribute](https://github.com/image-rs/organization/blob/master/CONTRIBUTING.md)
|
||||
|
||||
## An Image Processing Library
|
||||
|
||||
@ -10,23 +10,6 @@ This crate provides basic imaging processing functions and methods for convertin
|
||||
|
||||
All image processing functions provided operate on types that implement the ```GenericImage``` trait and return an ```ImageBuffer```.
|
||||
|
||||
### Usage
|
||||
|
||||
Add the following to the Cargo.toml in your project:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
image = "*"
|
||||
```
|
||||
|
||||
and import using ```extern crate```:
|
||||
|
||||
```rust
|
||||
extern crate image;
|
||||
|
||||
// use image::
|
||||
```
|
||||
|
||||
## 1. Documentation
|
||||
|
||||
https://docs.rs/image
|
||||
@ -42,7 +25,7 @@ https://docs.rs/image
|
||||
| GIF | Yes | Yes |
|
||||
| BMP | Yes | RGB(8), RGBA(8), Gray(8), GrayA(8) |
|
||||
| ICO | Yes | Yes |
|
||||
| TIFF | Baseline(no fax support) + LZW + PackBits | No |
|
||||
| TIFF | Baseline(no fax support) + LZW + PackBits | RGB(8), RGBA(8), Gray(8) |
|
||||
| Webp | Lossy(Luma channel only) | No |
|
||||
| PNM | PBM, PGM, PPM, standard PAM | Yes |
|
||||
|
||||
@ -69,6 +52,7 @@ All pixels are parameterised by their component type.
|
||||
A trait that provides functions for manipulating images, parameterised over the image's pixel type.
|
||||
|
||||
```rust
|
||||
# use image::{Pixel, Pixels};
|
||||
pub trait GenericImage {
|
||||
/// The pixel type.
|
||||
type Pixel: Pixel;
|
||||
@ -101,13 +85,13 @@ An image parameterised by its Pixel types, represented by a width and height and
|
||||
```rust
|
||||
extern crate image;
|
||||
|
||||
use image::{GenericImage, ImageBuffer};
|
||||
use image::{GenericImage, GenericImageView, ImageBuffer, RgbImage};
|
||||
|
||||
// Construct a new ImageBuffer with the specified width and height.
|
||||
let img = ImageBuffer::new(512, 512);
|
||||
// Construct a new RGB ImageBuffer with the specified width and height.
|
||||
let img: RgbImage = ImageBuffer::new(512, 512);
|
||||
|
||||
// Construct a new by repeated calls to the supplied closure.
|
||||
let img = ImageBuffer::from_fn(512, 512, |x, y| {
|
||||
let mut img = ImageBuffer::from_fn(512, 512, |x, y| {
|
||||
if x % 2 == 0 {
|
||||
image::Luma([0u8])
|
||||
} else {
|
||||
@ -122,7 +106,7 @@ let (width, height) = img.dimensions();
|
||||
let pixel = img[(100, 100)];
|
||||
|
||||
// Or use the ```get_pixel``` method from the ```GenericImage``` trait.
|
||||
let pixel = img.get_pixel(100, 100);
|
||||
let pixel = *img.get_pixel(100, 100);
|
||||
|
||||
// Put a pixel at coordinate (100, 100).
|
||||
img.put_pixel(100, 100, pixel);
|
||||
@ -147,10 +131,10 @@ This is used to perform image processing functions on a subregion of an image.
|
||||
```rust
|
||||
extern crate image;
|
||||
|
||||
use image::{GenericImage, ImageBuffer, imageops};
|
||||
use image::{GenericImageView, ImageBuffer, RgbImage, imageops};
|
||||
|
||||
let ref mut img = ImageBuffer::new(512, 512);
|
||||
let subimg = imageops::crop(img, 0, 0, 100, 100);
|
||||
let mut img: RgbImage = ImageBuffer::new(512, 512);
|
||||
let subimg = imageops::crop(&mut img, 0, 0, 100, 100);
|
||||
|
||||
assert!(subimg.dimensions() == (100, 100));
|
||||
```
|
||||
@ -180,7 +164,7 @@ These are the functions defined in the ```imageops``` module. All functions oper
|
||||
|
||||
The image format is determined from the path's file extension.
|
||||
|
||||
```rust
|
||||
```rust,no_run
|
||||
extern crate image;
|
||||
|
||||
use image::GenericImageView;
|
||||
@ -188,7 +172,7 @@ use image::GenericImageView;
|
||||
fn main() {
|
||||
// Use the open function to load an image from a Path.
|
||||
// ```open``` returns a `DynamicImage` on success.
|
||||
let img = image::open("test.jpg").unwrap();
|
||||
let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap();
|
||||
|
||||
// The dimensions method returns the images width and height.
|
||||
println!("dimensions {:?}", img.dimensions());
|
||||
@ -202,7 +186,7 @@ fn main() {
|
||||
```
|
||||
|
||||
### 6.2 Generating Fractals
|
||||
```rust
|
||||
```rust,no_run
|
||||
//! An example of generating julia fractals.
|
||||
extern crate image;
|
||||
extern crate num_complex;
|
||||
@ -240,7 +224,7 @@ fn main() {
|
||||
}
|
||||
|
||||
let pixel = imgbuf.get_pixel_mut(x, y);
|
||||
let data = (*pixel as image::Rgb<u8>).data;
|
||||
let image::Rgb(data) = *pixel;
|
||||
*pixel = image::Rgb([data[0], i as u8, data[2]]);
|
||||
}
|
||||
}
|
||||
@ -257,12 +241,12 @@ Example output:
|
||||
### 6.3 Writing raw buffers
|
||||
If the high level interface is not needed because the image was obtained by other means, `image` provides the function `save_buffer` to save a buffer to a file.
|
||||
|
||||
```rust
|
||||
```rust,no_run
|
||||
extern crate image;
|
||||
|
||||
fn main() {
|
||||
|
||||
let buffer: &[u8] = ...; // Generate the image data
|
||||
let buffer: &[u8] = unimplemented!(); // Generate the image data
|
||||
|
||||
// Save the buffer as "image.png"
|
||||
image::save_buffer("image.png", buffer, 800, 600, image::RGB(8)).unwrap()
|
||||
|
6
third_party/rust/image/benches/README.md
vendored
Normal file
6
third_party/rust/image/benches/README.md
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Getting started with benchmarking
|
||||
|
||||
To run the benchmarks you need a nightly rust toolchain.
|
||||
Then you launch it with
|
||||
|
||||
cargo +nightly bench --features=benchmarks
|
4
third_party/rust/image/src/animation.rs
vendored
4
third_party/rust/image/src/animation.rs
vendored
@ -7,12 +7,12 @@ use image::ImageResult;
|
||||
|
||||
/// An implementation dependent iterator, reading the frames as requested
|
||||
pub struct Frames<'a> {
|
||||
iterator: Box<Iterator<Item = ImageResult<Frame>> + 'a>
|
||||
iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
|
||||
}
|
||||
|
||||
impl<'a> Frames<'a> {
|
||||
/// Creates a new `Frames` from an implementation specific iterator.
|
||||
pub fn new(iterator: Box<Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
|
||||
pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
|
||||
Frames { iterator }
|
||||
}
|
||||
|
||||
|
172
third_party/rust/image/src/bmp/decoder.rs
vendored
172
third_party/rust/image/src/bmp/decoder.rs
vendored
@ -1,7 +1,7 @@
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom};
|
||||
use std::{cmp, mem};
|
||||
use std::io::{self, Cursor, Read, Seek, SeekFrom};
|
||||
use std::iter::{repeat, Iterator, Rev};
|
||||
use std::marker::PhantomData;
|
||||
use std::slice::ChunksMut;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
@ -217,19 +217,19 @@ where
|
||||
|
||||
if !top_down {
|
||||
for row in buffer.chunks_mut(row_width).rev() {
|
||||
try!(func(row));
|
||||
func(row)?;
|
||||
}
|
||||
|
||||
// If we need more space, extend the buffer.
|
||||
if buffer.len() < full_image_size {
|
||||
let new_space = extend_buffer(buffer, full_image_size, false);
|
||||
for row in new_space.chunks_mut(row_width).rev() {
|
||||
try!(func(row));
|
||||
func(row)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for row in buffer.chunks_mut(row_width) {
|
||||
try!(func(row));
|
||||
func(row)?;
|
||||
}
|
||||
if buffer.len() < full_image_size {
|
||||
// If the image is stored in top-down order, we can simply use the extend function
|
||||
@ -238,7 +238,7 @@ where
|
||||
buffer.extend(repeat(0xFF).take(extend));
|
||||
let len = buffer.len();
|
||||
for row in buffer[len - row_width..].chunks_mut(row_width) {
|
||||
try!(func(row));
|
||||
func(row)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -293,6 +293,37 @@ fn set_4bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
|
||||
true
|
||||
}
|
||||
|
||||
fn set_2bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
|
||||
pixel_iter: &mut ChunksMut<u8>,
|
||||
palette: &[(u8, u8, u8)],
|
||||
indices: T,
|
||||
mut n_pixels: usize,
|
||||
) -> bool {
|
||||
for idx in indices {
|
||||
macro_rules! set_pixel {
|
||||
($i:expr) => {
|
||||
if n_pixels == 0 {
|
||||
break;
|
||||
}
|
||||
if let Some(pixel) = pixel_iter.next() {
|
||||
let (r, g, b) = palette[$i as usize];
|
||||
pixel[0] = r;
|
||||
pixel[1] = g;
|
||||
pixel[2] = b;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
n_pixels -= 1;
|
||||
};
|
||||
}
|
||||
set_pixel!((idx >> 6) & 0x3u8);
|
||||
set_pixel!((idx >> 4) & 0x3u8);
|
||||
set_pixel!((idx >> 2) & 0x3u8);
|
||||
set_pixel!( idx & 0x3u8);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn set_1bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
|
||||
pixel_iter: &mut ChunksMut<u8>,
|
||||
palette: &[(u8, u8, u8)],
|
||||
@ -379,10 +410,10 @@ impl Bitfields {
|
||||
max_len: u32,
|
||||
) -> ImageResult<Bitfields> {
|
||||
let bitfields = Bitfields {
|
||||
r: try!(Bitfield::from_mask(r_mask, max_len)),
|
||||
g: try!(Bitfield::from_mask(g_mask, max_len)),
|
||||
b: try!(Bitfield::from_mask(b_mask, max_len)),
|
||||
a: try!(Bitfield::from_mask(a_mask, max_len)),
|
||||
r: Bitfield::from_mask(r_mask, max_len)?,
|
||||
g: Bitfield::from_mask(g_mask, max_len)?,
|
||||
b: Bitfield::from_mask(b_mask, max_len)?,
|
||||
a: Bitfield::from_mask(a_mask, max_len)?,
|
||||
};
|
||||
if bitfields.r.len == 0 || bitfields.g.len == 0 || bitfields.b.len == 0 {
|
||||
return Err(ImageError::FormatError("Missing bitfield mask".to_string()));
|
||||
@ -540,7 +571,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
return Ok(());
|
||||
}
|
||||
let mut signature = [0; 2];
|
||||
try!(self.r.read_exact(&mut signature));
|
||||
self.r.read_exact(&mut signature)?;
|
||||
|
||||
if signature != b"BM"[..] {
|
||||
return Err(ImageError::FormatError(
|
||||
@ -550,8 +581,8 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
|
||||
// The next 8 bytes represent file size, followed the 4 reserved bytes
|
||||
// We're not interesting these values
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
self.data_offset = u64::from(self.r.read_u32::<LittleEndian>()?);
|
||||
|
||||
@ -576,11 +607,11 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
// Number of planes (format specifies that this should be 1).
|
||||
if try!(self.r.read_u16::<LittleEndian>()) != 1 {
|
||||
return Err(ImageError::FormatError(
|
||||
"Invalid number of planes.".to_string(),
|
||||
"More than one plane".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
self.bit_count = try!(self.r.read_u16::<LittleEndian>());
|
||||
self.bit_count = self.r.read_u16::<LittleEndian>()?;
|
||||
self.image_type = match self.bit_count {
|
||||
1 | 4 | 8 => ImageType::Palette,
|
||||
24 => ImageType::RGB24,
|
||||
@ -595,8 +626,8 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
///
|
||||
/// returns Err if any of the values are invalid.
|
||||
fn read_bitmap_info_header(&mut self) -> ImageResult<()> {
|
||||
self.width = try!(self.r.read_i32::<LittleEndian>());
|
||||
self.height = try!(self.r.read_i32::<LittleEndian>());
|
||||
self.width = self.r.read_i32::<LittleEndian>()?;
|
||||
self.height = self.r.read_i32::<LittleEndian>()?;
|
||||
|
||||
// Width can not be negative
|
||||
if self.width < 0 {
|
||||
@ -626,12 +657,12 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
// Number of planes (format specifies that this should be 1).
|
||||
if try!(self.r.read_u16::<LittleEndian>()) != 1 {
|
||||
return Err(ImageError::FormatError(
|
||||
"Invalid number of planes.".to_string(),
|
||||
"More than one plane".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
self.bit_count = try!(self.r.read_u16::<LittleEndian>());
|
||||
let image_type_u32 = try!(self.r.read_u32::<LittleEndian>());
|
||||
self.bit_count = self.r.read_u16::<LittleEndian>()?;
|
||||
let image_type_u32 = self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
// Top-down dibs can not be compressed.
|
||||
if self.top_down && image_type_u32 != 0 && image_type_u32 != 3 {
|
||||
@ -641,7 +672,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
}
|
||||
self.image_type = match image_type_u32 {
|
||||
0 => match self.bit_count {
|
||||
1 | 4 | 8 => ImageType::Palette,
|
||||
1 | 2 | 4 | 8 => ImageType::Palette,
|
||||
16 => ImageType::RGB16,
|
||||
24 => ImageType::RGB24,
|
||||
32 => if self.add_alpha_channel {
|
||||
@ -649,7 +680,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
} else {
|
||||
ImageType::RGB32
|
||||
},
|
||||
_ => return Err(ImageError::FormatError("Invalid RGB bit count".to_string())),
|
||||
_ => return Err(ImageError::FormatError(format!("Invalid RGB bit count {}", self.bit_count).to_string())),
|
||||
},
|
||||
1 => match self.bit_count {
|
||||
8 => ImageType::RLE8,
|
||||
@ -688,23 +719,23 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
// followed the horizontal and vertical printing resolutions
|
||||
// We will calculate the pixel array size using width & height of image
|
||||
// We're not interesting the horz or vert printing resolutions
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
self.colors_used = try!(self.r.read_u32::<LittleEndian>());
|
||||
self.colors_used = self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
// The next 4 bytes represent number of "important" colors
|
||||
// We're not interested in this value, so we'll skip it
|
||||
try!(self.r.read_u32::<LittleEndian>());
|
||||
self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_bitmasks(&mut self) -> ImageResult<()> {
|
||||
let r_mask = try!(self.r.read_u32::<LittleEndian>());
|
||||
let g_mask = try!(self.r.read_u32::<LittleEndian>());
|
||||
let b_mask = try!(self.r.read_u32::<LittleEndian>());
|
||||
let r_mask = self.r.read_u32::<LittleEndian>()?;
|
||||
let g_mask = self.r.read_u32::<LittleEndian>()?;
|
||||
let b_mask = self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
let a_mask = match self.bmp_header_type {
|
||||
BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => {
|
||||
@ -732,9 +763,9 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
|
||||
fn read_metadata(&mut self) -> ImageResult<()> {
|
||||
if !self.has_loaded_metadata {
|
||||
try!(self.read_file_header());
|
||||
let bmp_header_offset = try!(self.r.seek(SeekFrom::Current(0)));
|
||||
let bmp_header_size = try!(self.r.read_u32::<LittleEndian>());
|
||||
self.read_file_header()?;
|
||||
let bmp_header_offset = self.r.seek(SeekFrom::Current(0))?;
|
||||
let bmp_header_size = self.r.read_u32::<LittleEndian>()?;
|
||||
let bmp_header_end = bmp_header_offset + u64::from(bmp_header_size);
|
||||
|
||||
self.bmp_header_type = match bmp_header_size {
|
||||
@ -753,32 +784,32 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
|
||||
match self.bmp_header_type {
|
||||
BMPHeaderType::Core => {
|
||||
try!(self.read_bitmap_core_header());
|
||||
self.read_bitmap_core_header()?;
|
||||
}
|
||||
BMPHeaderType::Info
|
||||
| BMPHeaderType::V2
|
||||
| BMPHeaderType::V3
|
||||
| BMPHeaderType::V4
|
||||
| BMPHeaderType::V5 => {
|
||||
try!(self.read_bitmap_info_header());
|
||||
self.read_bitmap_info_header()?;
|
||||
}
|
||||
};
|
||||
|
||||
match self.image_type {
|
||||
ImageType::Bitfields16 | ImageType::Bitfields32 => try!(self.read_bitmasks()),
|
||||
ImageType::Bitfields16 | ImageType::Bitfields32 => self.read_bitmasks()?,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
try!(self.r.seek(SeekFrom::Start(bmp_header_end)));
|
||||
self.r.seek(SeekFrom::Start(bmp_header_end))?;
|
||||
|
||||
match self.image_type {
|
||||
ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => try!(self.read_palette()),
|
||||
ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
if self.no_file_header {
|
||||
// Use the offset of the end of metadata instead of reading a BMP file header.
|
||||
self.data_offset = try!(self.r.seek(SeekFrom::Current(0)));
|
||||
self.data_offset = self.r.seek(SeekFrom::Current(0))?;
|
||||
}
|
||||
|
||||
self.has_loaded_metadata = true;
|
||||
@ -791,7 +822,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
pub fn read_metadata_in_ico_format(&mut self) -> ImageResult<()> {
|
||||
self.no_file_header = true;
|
||||
self.add_alpha_channel = true;
|
||||
try!(self.read_metadata());
|
||||
self.read_metadata()?;
|
||||
|
||||
// The height field in an ICO file is doubled to account for the AND mask
|
||||
// (whether or not an AND mask is actually present).
|
||||
@ -825,7 +856,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
const MAX_PALETTE_SIZE: usize = 256; // Palette indices are u8.
|
||||
|
||||
let bytes_per_color = self.bytes_per_color();
|
||||
let palette_size = try!(self.get_palette_size());
|
||||
let palette_size = self.get_palette_size()?;
|
||||
let max_length = MAX_PALETTE_SIZE * bytes_per_color;
|
||||
|
||||
let length = palette_size * bytes_per_color;
|
||||
@ -835,7 +866,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
// We limit the buffer to at most 256 colours to avoid any oom issues as
|
||||
// 8-bit images can't reference more than 256 indexes anyhow.
|
||||
buf.resize(cmp::min(length, max_length), 0);
|
||||
try!(self.r.by_ref().read_exact(&mut buf));
|
||||
self.r.by_ref().read_exact(&mut buf)?;
|
||||
|
||||
// Allocate 256 entries even if palette_size is smaller, to prevent corrupt files from
|
||||
// causing an out-of-bounds array access.
|
||||
@ -843,7 +874,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
buf.resize(max_length, 0);
|
||||
} else if length > max_length {
|
||||
// Ignore any excess palette colors.
|
||||
try!(self.r.seek(SeekFrom::Current((length - max_length) as i64)));
|
||||
self.r.seek(SeekFrom::Current((length - max_length) as i64))?;
|
||||
};
|
||||
|
||||
let p: Vec<(u8, u8, u8)> = (0..MAX_PALETTE_SIZE)
|
||||
@ -905,7 +936,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
let reader = &mut self.r;
|
||||
let width = self.width as usize;
|
||||
|
||||
try!(reader.seek(SeekFrom::Start(self.data_offset)));
|
||||
reader.seek(SeekFrom::Start(self.data_offset))?;
|
||||
|
||||
try!(with_rows(
|
||||
&mut pixel_data,
|
||||
@ -914,12 +945,15 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
num_channels,
|
||||
self.top_down,
|
||||
|row| {
|
||||
try!(reader.read_exact(&mut indices));
|
||||
reader.read_exact(&mut indices)?;
|
||||
let mut pixel_iter = row.chunks_mut(num_channels);
|
||||
match bit_count {
|
||||
1 => {
|
||||
set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter());
|
||||
}
|
||||
2 => {
|
||||
set_2bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
|
||||
}
|
||||
4 => {
|
||||
set_4bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
|
||||
}
|
||||
@ -946,7 +980,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
};
|
||||
let reader = &mut self.r;
|
||||
|
||||
try!(reader.seek(SeekFrom::Start(self.data_offset)));
|
||||
reader.seek(SeekFrom::Start(self.data_offset))?;
|
||||
|
||||
try!(with_rows(
|
||||
&mut pixel_data,
|
||||
@ -980,7 +1014,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
let bitfields = self.bitfields.as_ref().unwrap();
|
||||
|
||||
let reader = &mut self.r;
|
||||
try!(reader.seek(SeekFrom::Start(self.data_offset)));
|
||||
reader.seek(SeekFrom::Start(self.data_offset))?;
|
||||
|
||||
try!(with_rows(
|
||||
&mut pixel_data,
|
||||
@ -990,7 +1024,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
self.top_down,
|
||||
|row| {
|
||||
for pixel in row.chunks_mut(num_channels) {
|
||||
let data = try!(reader.read_u32::<LittleEndian>());
|
||||
let data = reader.read_u32::<LittleEndian>()?;
|
||||
|
||||
pixel[0] = bitfields.r.read(data);
|
||||
pixel[1] = bitfields.g.read(data);
|
||||
@ -1016,7 +1050,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
};
|
||||
let row_padding = &mut [0; 4][..row_padding_len];
|
||||
|
||||
try!(self.r.seek(SeekFrom::Start(self.data_offset)));
|
||||
self.r.seek(SeekFrom::Start(self.data_offset))?;
|
||||
|
||||
let reader = &mut self.r;
|
||||
|
||||
@ -1029,22 +1063,22 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
|row| {
|
||||
for pixel in row.chunks_mut(num_channels) {
|
||||
if *format == FormatFullBytes::Format888 {
|
||||
try!(reader.read_u8());
|
||||
reader.read_u8()?;
|
||||
}
|
||||
|
||||
// Read the colour values (b, g, r).
|
||||
// Reading 3 bytes and reversing them is significantly faster than reading one
|
||||
// at a time.
|
||||
try!(reader.read_exact(&mut pixel[0..3]));
|
||||
reader.read_exact(&mut pixel[0..3])?;
|
||||
pixel[0..3].reverse();
|
||||
|
||||
if *format == FormatFullBytes::RGB32 {
|
||||
try!(reader.read_u8());
|
||||
reader.read_u8()?;
|
||||
}
|
||||
|
||||
// Read the alpha channel if present
|
||||
if *format == FormatFullBytes::RGBA32 {
|
||||
try!(reader.read_exact(&mut pixel[3..4]));
|
||||
reader.read_exact(&mut pixel[3..4])?;
|
||||
}
|
||||
}
|
||||
reader.read_exact(row_padding)
|
||||
@ -1056,7 +1090,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
|
||||
fn read_rle_data(&mut self, image_type: ImageType) -> ImageResult<Vec<u8>> {
|
||||
// Seek to the start of the actual image data.
|
||||
try!(self.r.seek(SeekFrom::Start(self.data_offset)));
|
||||
self.r.seek(SeekFrom::Start(self.data_offset))?;
|
||||
|
||||
let full_image_size = try!(
|
||||
num_bytes(self.width, self.height, self.num_channels()).ok_or_else(|| {
|
||||
@ -1065,7 +1099,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
);
|
||||
let mut pixel_data = self.create_pixel_data();
|
||||
let (skip_pixels, skip_rows, eof_hit) =
|
||||
try!(self.read_rle_data_step(&mut pixel_data, image_type, 0, 0));
|
||||
self.read_rle_data_step(&mut pixel_data, image_type, 0, 0)?;
|
||||
// Extend the buffer if there is still data left.
|
||||
// If eof_hit is true, it means that we hit an end-of-file marker in the last step and
|
||||
// we won't extend the buffer further to avoid small files with a large specified size causing memory issues.
|
||||
@ -1073,7 +1107,7 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
// file would now have to at least have some data in it.
|
||||
if pixel_data.len() < full_image_size && !eof_hit {
|
||||
let new = extend_buffer(&mut pixel_data, full_image_size, true);
|
||||
try!(self.read_rle_data_step(new, image_type, skip_pixels, skip_rows));
|
||||
self.read_rle_data_step(new, image_type, skip_pixels, skip_rows)?;
|
||||
}
|
||||
Ok(pixel_data)
|
||||
}
|
||||
@ -1255,8 +1289,24 @@ impl<R: Read + Seek> BMPDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoder for BMPDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct BmpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for BmpReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for BMPDecoder<R> {
|
||||
type Reader = BmpReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.width as u64, self.height as u64)
|
||||
@ -1271,7 +1321,7 @@ impl<R: Read + Seek> ImageDecoder for BMPDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(BmpReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
@ -1279,7 +1329,7 @@ impl<R: Read + Seek> ImageDecoder for BMPDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoderExt for BMPDecoder<R> {
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoderExt<'a> for BMPDecoder<R> {
|
||||
fn read_rect_with_progress<F: Fn(Progress)>(
|
||||
&mut self,
|
||||
x: u64,
|
||||
|
141
third_party/rust/image/src/bmp/encoder.rs
vendored
141
third_party/rust/image/src/bmp/encoder.rs
vendored
@ -3,6 +3,10 @@ use std::io::{self, Write};
|
||||
|
||||
use color;
|
||||
|
||||
const BITMAPFILEHEADER_SIZE: u32 = 14;
|
||||
const BITMAPINFOHEADER_SIZE: u32 = 40;
|
||||
const BITMAPV4HEADER_SIZE: u32 = 108;
|
||||
|
||||
/// The representation of a BMP encoder.
|
||||
pub struct BMPEncoder<'a, W: 'a> {
|
||||
writer: &'a mut W,
|
||||
@ -24,10 +28,9 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
height: u32,
|
||||
c: color::ColorType,
|
||||
) -> io::Result<()> {
|
||||
let bmp_header_size = 14;
|
||||
let dib_header_size = 40; // using BITMAPINFOHEADER
|
||||
let bmp_header_size = BITMAPFILEHEADER_SIZE;
|
||||
|
||||
let (raw_pixel_size, written_pixel_size, palette_color_count) = try!(get_pixel_info(c));
|
||||
let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
|
||||
let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes
|
||||
|
||||
let image_size = width * height * written_pixel_size + (height * row_pad_size);
|
||||
@ -35,39 +38,62 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
let file_size = bmp_header_size + dib_header_size + palette_size + image_size;
|
||||
|
||||
// write BMP header
|
||||
try!(self.writer.write_u8(b'B'));
|
||||
try!(self.writer.write_u8(b'M'));
|
||||
try!(self.writer.write_u32::<LittleEndian>(file_size)); // file size
|
||||
try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 1
|
||||
try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 2
|
||||
self.writer.write_u8(b'B')?;
|
||||
self.writer.write_u8(b'M')?;
|
||||
self.writer.write_u32::<LittleEndian>(file_size)?; // file size
|
||||
self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
|
||||
self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
|
||||
try!(
|
||||
self.writer
|
||||
.write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)
|
||||
); // image data offset
|
||||
|
||||
// write DIB header
|
||||
try!(self.writer.write_u32::<LittleEndian>(dib_header_size));
|
||||
try!(self.writer.write_i32::<LittleEndian>(width as i32));
|
||||
try!(self.writer.write_i32::<LittleEndian>(height as i32));
|
||||
try!(self.writer.write_u16::<LittleEndian>(1)); // color planes
|
||||
self.writer.write_u32::<LittleEndian>(dib_header_size)?;
|
||||
self.writer.write_i32::<LittleEndian>(width as i32)?;
|
||||
self.writer.write_i32::<LittleEndian>(height as i32)?;
|
||||
self.writer.write_u16::<LittleEndian>(1)?; // color planes
|
||||
try!(
|
||||
self.writer
|
||||
.write_u16::<LittleEndian>((written_pixel_size * 8) as u16)
|
||||
); // bits per pixel
|
||||
try!(self.writer.write_u32::<LittleEndian>(0)); // compression method - no compression
|
||||
try!(self.writer.write_u32::<LittleEndian>(image_size));
|
||||
try!(self.writer.write_i32::<LittleEndian>(0)); // horizontal ppm
|
||||
try!(self.writer.write_i32::<LittleEndian>(0)); // vertical ppm
|
||||
try!(self.writer.write_u32::<LittleEndian>(palette_color_count));
|
||||
try!(self.writer.write_u32::<LittleEndian>(0)); // all colors are important
|
||||
if dib_header_size >= BITMAPV4HEADER_SIZE {
|
||||
// Assume BGRA32
|
||||
self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
|
||||
} else {
|
||||
self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
|
||||
}
|
||||
self.writer.write_u32::<LittleEndian>(image_size)?;
|
||||
self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
|
||||
self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
|
||||
self.writer.write_u32::<LittleEndian>(palette_color_count)?;
|
||||
self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
|
||||
if dib_header_size >= BITMAPV4HEADER_SIZE {
|
||||
// Assume BGRA32
|
||||
self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
|
||||
self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
|
||||
self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
|
||||
self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
|
||||
self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB
|
||||
// endpoints (3x3) and gamma (3)
|
||||
for _ in 0..12 {
|
||||
self.writer.write_u32::<LittleEndian>(0)?;
|
||||
}
|
||||
}
|
||||
|
||||
// write image data
|
||||
match c {
|
||||
color::ColorType::RGB(8) | color::ColorType::RGBA(8) => {
|
||||
try!(self.encode_rgb(image, width, height, row_pad_size, raw_pixel_size))
|
||||
color::ColorType::RGB(8) => {
|
||||
self.encode_rgb(image, width, height, row_pad_size, 3)?
|
||||
}
|
||||
color::ColorType::Gray(8) | color::ColorType::GrayA(8) => {
|
||||
try!(self.encode_gray(image, width, height, row_pad_size, raw_pixel_size))
|
||||
color::ColorType::RGBA(8) => {
|
||||
self.encode_rgba(image, width, height, row_pad_size, 4)?
|
||||
}
|
||||
color::ColorType::Gray(8) => {
|
||||
self.encode_gray(image, width, height, row_pad_size, 1)?
|
||||
}
|
||||
color::ColorType::GrayA(8) => {
|
||||
self.encode_gray(image, width, height, row_pad_size, 2)?
|
||||
}
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
@ -99,13 +125,45 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
let g = image[pixel_start + 1];
|
||||
let b = image[pixel_start + 2];
|
||||
// written as BGR
|
||||
try!(self.writer.write_u8(b));
|
||||
try!(self.writer.write_u8(g));
|
||||
try!(self.writer.write_u8(r));
|
||||
self.writer.write_u8(b)?;
|
||||
self.writer.write_u8(g)?;
|
||||
self.writer.write_u8(r)?;
|
||||
// alpha is never written as it's not widely supported
|
||||
}
|
||||
|
||||
try!(self.write_row_pad(row_pad_size));
|
||||
self.write_row_pad(row_pad_size)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn encode_rgba(
|
||||
&mut self,
|
||||
image: &[u8],
|
||||
width: u32,
|
||||
height: u32,
|
||||
row_pad_size: u32,
|
||||
bytes_per_pixel: u32,
|
||||
) -> io::Result<()> {
|
||||
let x_stride = bytes_per_pixel;
|
||||
let y_stride = width * x_stride;
|
||||
for row in 0..height {
|
||||
// from the bottom up
|
||||
let row_start = (height - row - 1) * y_stride;
|
||||
for col in 0..width {
|
||||
let pixel_start = (row_start + (col * x_stride)) as usize;
|
||||
let r = image[pixel_start];
|
||||
let g = image[pixel_start + 1];
|
||||
let b = image[pixel_start + 2];
|
||||
let a = image[pixel_start + 3];
|
||||
// written as BGRA
|
||||
self.writer.write_u8(b)?;
|
||||
self.writer.write_u8(g)?;
|
||||
self.writer.write_u8(r)?;
|
||||
self.writer.write_u8(a)?;
|
||||
}
|
||||
|
||||
self.write_row_pad(row_pad_size)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -123,10 +181,10 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
for val in 0..256 {
|
||||
// each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
|
||||
let val = val as u8;
|
||||
try!(self.writer.write_u8(val));
|
||||
try!(self.writer.write_u8(val));
|
||||
try!(self.writer.write_u8(val));
|
||||
try!(self.writer.write_u8(0));
|
||||
self.writer.write_u8(val)?;
|
||||
self.writer.write_u8(val)?;
|
||||
self.writer.write_u8(val)?;
|
||||
self.writer.write_u8(0)?;
|
||||
}
|
||||
|
||||
// write image data
|
||||
@ -138,11 +196,11 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
for col in 0..width {
|
||||
let pixel_start = (row_start + (col * x_stride)) as usize;
|
||||
// color value is equal to the palette index
|
||||
try!(self.writer.write_u8(image[pixel_start]));
|
||||
self.writer.write_u8(image[pixel_start])?;
|
||||
// alpha is never written as it's not widely supported
|
||||
}
|
||||
|
||||
try!(self.write_row_pad(row_pad_size));
|
||||
self.write_row_pad(row_pad_size)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -150,7 +208,7 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
|
||||
|
||||
fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
|
||||
for _ in 0..row_pad_size {
|
||||
try!(self.writer.write_u8(0));
|
||||
self.writer.write_u8(0)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -164,13 +222,13 @@ fn get_unsupported_error_message(c: color::ColorType) -> String {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a tuple representing: (raw pixel size, written pixel size, palette color count).
|
||||
/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
|
||||
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
|
||||
let sizes = match c {
|
||||
color::ColorType::RGB(8) => (3, 3, 0),
|
||||
color::ColorType::RGBA(8) => (4, 3, 0),
|
||||
color::ColorType::Gray(8) => (1, 1, 256),
|
||||
color::ColorType::GrayA(8) => (2, 1, 256),
|
||||
color::ColorType::RGB(8) => (BITMAPINFOHEADER_SIZE, 3, 0),
|
||||
color::ColorType::RGBA(8) => (BITMAPV4HEADER_SIZE, 4, 0),
|
||||
color::ColorType::Gray(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
|
||||
color::ColorType::GrayA(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -215,12 +273,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn round_trip_single_pixel_rgba() {
|
||||
let image = [255u8, 0, 0, 0]; // single red pixel
|
||||
let image = [1, 2, 3, 4];
|
||||
let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
|
||||
assert_eq!(3, decoded.len());
|
||||
assert_eq!(255, decoded[0]);
|
||||
assert_eq!(0, decoded[1]);
|
||||
assert_eq!(0, decoded[2]);
|
||||
assert_eq!(&decoded[..], &image[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
327
third_party/rust/image/src/buffer.rs
vendored
327
third_party/rust/image/src/buffer.rs
vendored
@ -7,8 +7,8 @@ use std::slice::{Chunks, ChunksMut};
|
||||
|
||||
use color::{ColorType, FromColor, Luma, LumaA, Rgb, Rgba, Bgr, Bgra};
|
||||
use flat::{FlatSamples, SampleLayout};
|
||||
use dynimage::save_buffer;
|
||||
use image::{GenericImage, GenericImageView};
|
||||
use dynimage::{save_buffer, save_buffer_with_format};
|
||||
use image::{GenericImage, GenericImageView, ImageFormat};
|
||||
use traits::Primitive;
|
||||
use utils::expand_packed;
|
||||
|
||||
@ -19,8 +19,13 @@ pub trait Pixel: Copy + Clone {
|
||||
/// The underlying subpixel type.
|
||||
type Subpixel: Primitive;
|
||||
|
||||
/// The number of channels of this pixel type.
|
||||
const CHANNEL_COUNT: u8;
|
||||
/// Returns the number of channels of this pixel type.
|
||||
fn channel_count() -> u8;
|
||||
#[deprecated(note="please use CHANNEL_COUNT associated constant")]
|
||||
fn channel_count() -> u8 {
|
||||
Self::CHANNEL_COUNT
|
||||
}
|
||||
|
||||
/// Returns the components as a slice.
|
||||
fn channels(&self) -> &[Self::Subpixel];
|
||||
@ -28,12 +33,23 @@ pub trait Pixel: Copy + Clone {
|
||||
/// Returns the components as a mutable slice
|
||||
fn channels_mut(&mut self) -> &mut [Self::Subpixel];
|
||||
|
||||
/// A string that can help to interpret the meaning each channel
|
||||
/// See [gimp babl](http://gegl.org/babl/).
|
||||
const COLOR_MODEL: &'static str;
|
||||
/// Returns a string that can help to interpret the meaning each channel
|
||||
/// See [gimp babl](http://gegl.org/babl/).
|
||||
fn color_model() -> &'static str;
|
||||
#[deprecated(note="please use COLOR_MODEL associated constant")]
|
||||
fn color_model() -> &'static str {
|
||||
Self::COLOR_MODEL
|
||||
}
|
||||
|
||||
/// ColorType for this pixel format
|
||||
const COLOR_TYPE: ColorType;
|
||||
/// Returns the ColorType for this pixel format
|
||||
fn color_type() -> ColorType;
|
||||
#[deprecated(note="please use COLOR_TYPE associated constant")]
|
||||
fn color_type() -> ColorType {
|
||||
Self::COLOR_TYPE
|
||||
}
|
||||
|
||||
/// Returns the channels of this pixel as a 4 tuple. If the pixel
|
||||
/// has less than 4 channels the remainder is filled with the maximum value
|
||||
@ -112,6 +128,25 @@ pub trait Pixel: Copy + Clone {
|
||||
where
|
||||
F: FnMut(Self::Subpixel) -> Self::Subpixel,
|
||||
G: FnMut(Self::Subpixel) -> Self::Subpixel;
|
||||
|
||||
/// Apply the function ```f``` to each channel except the alpha channel.
|
||||
fn map_without_alpha<F>(&self, f: F) -> Self
|
||||
where
|
||||
F: FnMut(Self::Subpixel) -> Self::Subpixel,
|
||||
{
|
||||
let mut this = *self;
|
||||
this.apply_with_alpha(f, |x| x);
|
||||
this
|
||||
}
|
||||
|
||||
/// Apply the function ```f``` to each channel except the alpha channel.
|
||||
/// Works in place.
|
||||
fn apply_without_alpha<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnMut(Self::Subpixel) -> Self::Subpixel,
|
||||
{
|
||||
self.apply_with_alpha(f, |x| x);
|
||||
}
|
||||
|
||||
/// Apply the function ```f``` to each channel of this pixel and
|
||||
/// ```other``` pairwise.
|
||||
@ -212,6 +247,92 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate over rows of an image
|
||||
pub struct Rows<'a, P: Pixel + 'a>
|
||||
where
|
||||
<P as Pixel>::Subpixel: 'a,
|
||||
{
|
||||
chunks: Chunks<'a, P::Subpixel>,
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
type Item = Pixels<'a, P>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Pixels<'a, P>> {
|
||||
self.chunks.next().map(|row| Pixels {
|
||||
chunks: row.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.chunks.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn next_back(&mut self) -> Option<Pixels<'a, P>> {
|
||||
self.chunks.next_back().map(|row| Pixels {
|
||||
chunks: row.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate over mutable rows of an image
|
||||
pub struct RowsMut<'a, P: Pixel + 'a>
|
||||
where
|
||||
<P as Pixel>::Subpixel: 'a,
|
||||
{
|
||||
chunks: ChunksMut<'a, P::Subpixel>,
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
type Item = PixelsMut<'a, P>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<PixelsMut<'a, P>> {
|
||||
self.chunks.next().map(|row| PixelsMut {
|
||||
chunks: row.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.chunks.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn next_back(&mut self) -> Option<PixelsMut<'a, P>> {
|
||||
self.chunks.next_back().map(|row| PixelsMut {
|
||||
chunks: row.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate the pixels of an image.
|
||||
pub struct EnumeratePixels<'a, P: Pixel + 'a>
|
||||
where
|
||||
@ -237,10 +358,7 @@ where
|
||||
}
|
||||
let (x, y) = (self.x, self.y);
|
||||
self.x += 1;
|
||||
match self.pixels.next() {
|
||||
None => None,
|
||||
Some(p) => Some((x, y, p)),
|
||||
}
|
||||
self.pixels.next().map(|p| (x, y, p))
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,6 +371,49 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate the rows of an image.
|
||||
pub struct EnumerateRows<'a, P: Pixel + 'a>
|
||||
where
|
||||
<P as Pixel>::Subpixel: 'a,
|
||||
{
|
||||
rows: Rows<'a, P>,
|
||||
y: u32,
|
||||
width: u32,
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
type Item = (u32, EnumeratePixels<'a, P>);
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> {
|
||||
let y = self.y;
|
||||
self.y += 1;
|
||||
self.rows.next().map(|r| {
|
||||
(
|
||||
y,
|
||||
EnumeratePixels {
|
||||
x: 0,
|
||||
y,
|
||||
width: self.width,
|
||||
pixels: r,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.rows.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate the pixels of an image.
|
||||
pub struct EnumeratePixelsMut<'a, P: Pixel + 'a>
|
||||
where
|
||||
@ -278,10 +439,7 @@ where
|
||||
}
|
||||
let (x, y) = (self.x, self.y);
|
||||
self.x += 1;
|
||||
match self.pixels.next() {
|
||||
None => None,
|
||||
Some(p) => Some((x, y, p)),
|
||||
}
|
||||
self.pixels.next().map(|p| (x, y, p))
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +452,49 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate the rows of an image.
|
||||
pub struct EnumerateRowsMut<'a, P: Pixel + 'a>
|
||||
where
|
||||
<P as Pixel>::Subpixel: 'a,
|
||||
{
|
||||
rows: RowsMut<'a, P>,
|
||||
y: u32,
|
||||
width: u32,
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
type Item = (u32, EnumeratePixelsMut<'a, P>);
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> {
|
||||
let y = self.y;
|
||||
self.y += 1;
|
||||
self.rows.next().map(|r| {
|
||||
(
|
||||
y,
|
||||
EnumeratePixelsMut {
|
||||
x: 0,
|
||||
y,
|
||||
width: self.width,
|
||||
pixels: r,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P>
|
||||
where
|
||||
P::Subpixel: 'a,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.rows.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic image buffer
|
||||
#[derive(Debug)]
|
||||
pub struct ImageBuffer<P: Pixel, Container> {
|
||||
@ -304,6 +505,9 @@ pub struct ImageBuffer<P: Pixel, Container> {
|
||||
}
|
||||
|
||||
// generic implementation, shared along all image buffers
|
||||
//
|
||||
// TODO: Is the 'static bound on `I::Pixel` really required? Can we avoid it? Remember to remove
|
||||
// the bounds on `imageops` in case this changes!
|
||||
impl<P, Container> ImageBuffer<P, Container>
|
||||
where
|
||||
P: Pixel + 'static,
|
||||
@ -351,7 +555,16 @@ where
|
||||
/// Returns an iterator over the pixels of this image.
|
||||
pub fn pixels(&self) -> Pixels<P> {
|
||||
Pixels {
|
||||
chunks: self.data.chunks(<P as Pixel>::channel_count() as usize),
|
||||
chunks: self.data.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the rows of this image.
|
||||
pub fn rows(&self) -> Rows<P> {
|
||||
Rows {
|
||||
chunks: self
|
||||
.data
|
||||
.chunks(<P as Pixel>::CHANNEL_COUNT as usize * self.width as usize),
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,6 +580,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerates over the rows of the image.
|
||||
/// The iterator yields the y-coordinate of each row
|
||||
/// along with a reference to them.
|
||||
pub fn enumerate_rows(&self) -> EnumerateRows<P> {
|
||||
EnumerateRows {
|
||||
rows: self.rows(),
|
||||
y: 0,
|
||||
width: self.width,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a reference to the pixel at location `(x, y)`
|
||||
///
|
||||
/// # Panics
|
||||
@ -390,7 +614,7 @@ where
|
||||
}
|
||||
|
||||
fn image_buffer_len(width: u32, height: u32) -> Option<usize> {
|
||||
Some(<P as Pixel>::channel_count() as usize)
|
||||
Some(<P as Pixel>::CHANNEL_COUNT as usize)
|
||||
.and_then(|size| size.checked_mul(width as usize))
|
||||
.and_then(|size| size.checked_mul(height as usize))
|
||||
}
|
||||
@ -401,14 +625,12 @@ where
|
||||
return None
|
||||
}
|
||||
|
||||
Some(unsafe {
|
||||
self.unsafe_pixel_indices(x, y)
|
||||
})
|
||||
Some(self.pixel_indices_unchecked(x, y))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn unsafe_pixel_indices(&self, x: u32, y: u32) -> Range<usize> {
|
||||
let no_channels = <P as Pixel>::channel_count() as usize;
|
||||
fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range<usize> {
|
||||
let no_channels = <P as Pixel>::CHANNEL_COUNT as usize;
|
||||
// If in bounds, this can't overflow as we have tested that at construction!
|
||||
let min_index = (y as usize*self.width as usize + x as usize)*no_channels;
|
||||
min_index..min_index+no_channels
|
||||
@ -417,7 +639,7 @@ where
|
||||
/// Get the format of the buffer when viewed as a matrix of samples.
|
||||
pub fn sample_layout(&self) -> SampleLayout {
|
||||
// None of these can overflow, as all our memory is addressable.
|
||||
SampleLayout::row_major_packed(<P as Pixel>::channel_count(), self.width, self.height)
|
||||
SampleLayout::row_major_packed(<P as Pixel>::CHANNEL_COUNT, self.width, self.height)
|
||||
}
|
||||
|
||||
/// Return the raw sample buffer with its stride an dimension information.
|
||||
@ -434,7 +656,7 @@ where
|
||||
FlatSamples {
|
||||
samples: self.data,
|
||||
layout,
|
||||
color_hint: Some(P::color_type()),
|
||||
color_hint: Some(P::COLOR_TYPE),
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +670,7 @@ where
|
||||
FlatSamples {
|
||||
samples: self.data.as_ref(),
|
||||
layout,
|
||||
color_hint: Some(P::color_type()),
|
||||
color_hint: Some(P::COLOR_TYPE),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,7 +684,16 @@ where
|
||||
/// Returns an iterator over the mutable pixels of this image.
|
||||
pub fn pixels_mut(&mut self) -> PixelsMut<P> {
|
||||
PixelsMut {
|
||||
chunks: self.data.chunks_mut(<P as Pixel>::channel_count() as usize),
|
||||
chunks: self.data.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the mutable rows of this image.
|
||||
pub fn rows_mut(&mut self) -> RowsMut<P> {
|
||||
RowsMut {
|
||||
chunks: self
|
||||
.data
|
||||
.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize * self.width as usize),
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,6 +710,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerates over the rows of the image.
|
||||
/// The iterator yields the y-coordinate of each row
|
||||
/// along with a mutable reference to them.
|
||||
pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<P> {
|
||||
let width = self.width;
|
||||
EnumerateRowsMut {
|
||||
rows: self.rows_mut(),
|
||||
y: 0,
|
||||
width,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a reference to the mutable pixel at location `(x, y)`
|
||||
///
|
||||
/// # Panics
|
||||
@ -520,7 +763,33 @@ where
|
||||
self,
|
||||
self.width(),
|
||||
self.height(),
|
||||
<P as Pixel>::color_type(),
|
||||
<P as Pixel>::COLOR_TYPE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, Container> ImageBuffer<P, Container>
|
||||
where
|
||||
P: Pixel<Subpixel = u8> + 'static,
|
||||
Container: Deref<Target = [u8]>,
|
||||
{
|
||||
/// Saves the buffer to a file at the specified path in
|
||||
/// the specified format.
|
||||
///
|
||||
/// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
|
||||
/// supported types.
|
||||
pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> io::Result<()>
|
||||
where
|
||||
Q: AsRef<Path>,
|
||||
{
|
||||
// This is valid as the subpixel is u8.
|
||||
save_buffer_with_format(
|
||||
path,
|
||||
self,
|
||||
self.width(),
|
||||
self.height(),
|
||||
<P as Pixel>::COLOR_TYPE,
|
||||
format,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -612,7 +881,7 @@ where
|
||||
/// Returns the pixel located at (x, y), ignoring bounds checking.
|
||||
#[inline(always)]
|
||||
unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P {
|
||||
let indices = self.unsafe_pixel_indices(x, y);
|
||||
let indices = self.pixel_indices_unchecked(x, y);
|
||||
*<P as Pixel>::from_slice(self.data.get_unchecked(indices))
|
||||
}
|
||||
|
||||
@ -640,7 +909,7 @@ where
|
||||
/// Puts a pixel at location (x, y), ignoring bounds checking.
|
||||
#[inline(always)]
|
||||
unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) {
|
||||
let indices = self.unsafe_pixel_indices(x, y);
|
||||
let indices = self.pixel_indices_unchecked(x, y);
|
||||
let p = <P as Pixel>::from_slice_mut(self.data.get_unchecked_mut(indices));
|
||||
*p = pixel
|
||||
}
|
||||
@ -753,9 +1022,7 @@ impl GrayImage {
|
||||
let (width, height) = self.dimensions();
|
||||
let mut data = self.into_raw();
|
||||
let entries = data.len();
|
||||
data.reserve_exact(entries.checked_mul(3).unwrap()); // 3 additional channels
|
||||
// set_len is save since type is u8 an the data never read
|
||||
unsafe { data.set_len(entries.checked_mul(4).unwrap()) }; // 4 channels in total
|
||||
data.resize(entries.checked_mul(4).unwrap(), 0);
|
||||
let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap();
|
||||
expand_packed(&mut buffer, 4, 8, |idx, pixel| {
|
||||
let (r, g, b) = palette[idx as usize];
|
||||
|
271
third_party/rust/image/src/color.rs
vendored
271
third_party/rust/image/src/color.rs
vendored
@ -68,40 +68,31 @@ $( // START Structure definitions
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct $ident<T: Primitive> { pub data: [T; $channels] }
|
||||
#[allow(non_snake_case, missing_docs)]
|
||||
pub fn $ident<T: Primitive>(data: [T; $channels]) -> $ident<T> {
|
||||
$ident {
|
||||
data: data
|
||||
}
|
||||
}
|
||||
pub struct $ident<T: Primitive> (pub [T; $channels]);
|
||||
|
||||
impl<T: Primitive + 'static> Pixel for $ident<T> {
|
||||
|
||||
type Subpixel = T;
|
||||
|
||||
fn channel_count() -> u8 {
|
||||
$channels
|
||||
}
|
||||
fn color_model() -> &'static str {
|
||||
$interpretation
|
||||
}
|
||||
fn color_type() -> ColorType {
|
||||
ColorType::$color_type(mem::size_of::<T>() as u8 * 8)
|
||||
}
|
||||
const CHANNEL_COUNT: u8 = $channels;
|
||||
|
||||
const COLOR_MODEL: &'static str = $interpretation;
|
||||
|
||||
const COLOR_TYPE: ColorType = ColorType::$color_type(mem::size_of::<T>() as u8 * 8);
|
||||
|
||||
#[inline(always)]
|
||||
fn channels(&self) -> &[T] {
|
||||
&self.data
|
||||
&self.0
|
||||
}
|
||||
#[inline(always)]
|
||||
fn channels_mut(&mut self) -> &mut [T] {
|
||||
&mut self.data
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
#[allow(trivial_casts)]
|
||||
fn channels4(&self) -> (T, T, T, T) {
|
||||
let mut channels = [T::max_value(); 4];
|
||||
channels[0..$channels].copy_from_slice(&self.data);
|
||||
channels[0..$channels].copy_from_slice(&self.0);
|
||||
(channels[0], channels[1], channels[2], channels[3])
|
||||
}
|
||||
|
||||
@ -119,37 +110,37 @@ impl<T: Primitive + 'static> Pixel for $ident<T> {
|
||||
}
|
||||
|
||||
fn to_rgb(&self) -> Rgb<T> {
|
||||
let mut pix = Rgb {data: [Zero::zero(), Zero::zero(), Zero::zero()]};
|
||||
let mut pix = Rgb([Zero::zero(), Zero::zero(), Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
|
||||
fn to_bgr(&self) -> Bgr<T> {
|
||||
let mut pix = Bgr {data: [Zero::zero(), Zero::zero(), Zero::zero()]};
|
||||
let mut pix = Bgr([Zero::zero(), Zero::zero(), Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
|
||||
fn to_rgba(&self) -> Rgba<T> {
|
||||
let mut pix = Rgba {data: [Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]};
|
||||
let mut pix = Rgba([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
|
||||
fn to_bgra(&self) -> Bgra<T> {
|
||||
let mut pix = Bgra {data: [Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]};
|
||||
let mut pix = Bgra([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
|
||||
fn to_luma(&self) -> Luma<T> {
|
||||
let mut pix = Luma {data: [Zero::zero()]};
|
||||
let mut pix = Luma([Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
|
||||
fn to_luma_alpha(&self) -> LumaA<T> {
|
||||
let mut pix = LumaA {data: [Zero::zero(), Zero::zero()]};
|
||||
let mut pix = LumaA([Zero::zero(), Zero::zero()]);
|
||||
pix.from_color(self);
|
||||
pix
|
||||
}
|
||||
@ -161,7 +152,7 @@ impl<T: Primitive + 'static> Pixel for $ident<T> {
|
||||
}
|
||||
|
||||
fn apply<F>(&mut self, mut f: F) where F: FnMut(T) -> T {
|
||||
for v in &mut self.data {
|
||||
for v in &mut self.0 {
|
||||
*v = f(*v)
|
||||
}
|
||||
}
|
||||
@ -174,11 +165,11 @@ impl<T: Primitive + 'static> Pixel for $ident<T> {
|
||||
|
||||
#[allow(trivial_casts)]
|
||||
fn apply_with_alpha<F, G>(&mut self, mut f: F, mut g: G) where F: FnMut(T) -> T, G: FnMut(T) -> T {
|
||||
for v in self.data[..$channels as usize-$alphas as usize].iter_mut() {
|
||||
for v in self.0[..$channels as usize-$alphas as usize].iter_mut() {
|
||||
*v = f(*v)
|
||||
}
|
||||
if $alphas as usize != 0 {
|
||||
let v = &mut self.data[$channels as usize-$alphas as usize];
|
||||
let v = &mut self.0[$channels as usize-$alphas as usize];
|
||||
*v = g(*v)
|
||||
}
|
||||
}
|
||||
@ -190,7 +181,7 @@ impl<T: Primitive + 'static> Pixel for $ident<T> {
|
||||
}
|
||||
|
||||
fn apply2<F>(&mut self, other: &$ident<T>, mut f: F) where F: FnMut(T, T) -> T {
|
||||
for (a, &b) in self.data.iter_mut().zip(other.data.iter()) {
|
||||
for (a, &b) in self.0.iter_mut().zip(other.0.iter()) {
|
||||
*a = f(*a, b)
|
||||
}
|
||||
}
|
||||
@ -208,14 +199,14 @@ impl<T: Primitive> Index<usize> for $ident<T> {
|
||||
type Output = T;
|
||||
#[inline(always)]
|
||||
fn index(&self, _index: usize) -> &T {
|
||||
&self.data[_index]
|
||||
&self.0[_index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Primitive> IndexMut<usize> for $ident<T> {
|
||||
#[inline(always)]
|
||||
fn index_mut(&mut self, _index: usize) -> &mut T {
|
||||
&mut self.data[_index]
|
||||
&mut self.0[_index]
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,8 +580,8 @@ impl<T: Primitive> Blend for LumaA<T> {
|
||||
fn blend(&mut self, other: &LumaA<T>) {
|
||||
let max_t = T::max_value();
|
||||
let max_t = max_t.to_f32().unwrap();
|
||||
let (bg_luma, bg_a) = (self.data[0], self.data[1]);
|
||||
let (fg_luma, fg_a) = (other.data[0], other.data[1]);
|
||||
let (bg_luma, bg_a) = (self.0[0], self.0[1]);
|
||||
let (fg_luma, fg_a) = (other.0[0], other.0[1]);
|
||||
|
||||
let (bg_luma, bg_a) = (
|
||||
bg_luma.to_f32().unwrap() / max_t,
|
||||
@ -631,8 +622,8 @@ impl<T: Primitive> Blend for Rgba<T> {
|
||||
// First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0
|
||||
let max_t = T::max_value();
|
||||
let max_t = max_t.to_f32().unwrap();
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (self.data[0], self.data[1], self.data[2], self.data[3]);
|
||||
let (fg_r, fg_g, fg_b, fg_a) = (other.data[0], other.data[1], other.data[2], other.data[3]);
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (self.0[0], self.0[1], self.0[2], self.0[3]);
|
||||
let (fg_r, fg_g, fg_b, fg_a) = (other.0[0], other.0[1], other.0[2], other.0[3]);
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (
|
||||
bg_r.to_f32().unwrap() / max_t,
|
||||
bg_g.to_f32().unwrap() / max_t,
|
||||
@ -689,8 +680,8 @@ impl<T: Primitive> Blend for Bgra<T> {
|
||||
// First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0
|
||||
let max_t = T::max_value();
|
||||
let max_t = max_t.to_f32().unwrap();
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (self.data[2], self.data[1], self.data[0], self.data[3]);
|
||||
let (fg_r, fg_g, fg_b, fg_a) = (other.data[2], other.data[1], other.data[0], other.data[3]);
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (self.0[2], self.0[1], self.0[0], self.0[3]);
|
||||
let (fg_r, fg_g, fg_b, fg_a) = (other.0[2], other.0[1], other.0[0], other.0[3]);
|
||||
let (bg_r, bg_g, bg_b, bg_a) = (
|
||||
bg_r.to_f32().unwrap() / max_t,
|
||||
bg_g.to_f32().unwrap() / max_t,
|
||||
@ -759,7 +750,7 @@ pub trait Invert {
|
||||
|
||||
impl<T: Primitive> Invert for LumaA<T> {
|
||||
fn invert(&mut self) {
|
||||
let l = self.data;
|
||||
let l = self.0;
|
||||
let max = T::max_value();
|
||||
|
||||
*self = LumaA([max - l[0], l[1]])
|
||||
@ -768,18 +759,18 @@ impl<T: Primitive> Invert for LumaA<T> {
|
||||
|
||||
impl<T: Primitive> Invert for Luma<T> {
|
||||
fn invert(&mut self) {
|
||||
let l = self.data;
|
||||
let l = self.0;
|
||||
|
||||
let max = T::max_value();
|
||||
let l1 = max - l[0];
|
||||
|
||||
*self = Luma { data: [l1] }
|
||||
*self = Luma([l1])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Primitive> Invert for Rgba<T> {
|
||||
fn invert(&mut self) {
|
||||
let rgba = self.data;
|
||||
let rgba = self.0;
|
||||
|
||||
let max = T::max_value();
|
||||
|
||||
@ -790,7 +781,7 @@ impl<T: Primitive> Invert for Rgba<T> {
|
||||
|
||||
impl<T: Primitive> Invert for Bgra<T> {
|
||||
fn invert(&mut self) {
|
||||
let bgra = self.data;
|
||||
let bgra = self.0;
|
||||
|
||||
let max = T::max_value();
|
||||
|
||||
@ -801,7 +792,7 @@ impl<T: Primitive> Invert for Bgra<T> {
|
||||
|
||||
impl<T: Primitive> Invert for Rgb<T> {
|
||||
fn invert(&mut self) {
|
||||
let rgb = self.data;
|
||||
let rgb = self.0;
|
||||
|
||||
let max = T::max_value();
|
||||
|
||||
@ -815,7 +806,7 @@ impl<T: Primitive> Invert for Rgb<T> {
|
||||
|
||||
impl<T: Primitive> Invert for Bgr<T> {
|
||||
fn invert(&mut self) {
|
||||
let bgr = self.data;
|
||||
let bgr = self.0;
|
||||
|
||||
let max = T::max_value();
|
||||
|
||||
@ -833,157 +824,157 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_apply_with_alpha_rgba() {
|
||||
let mut rgba = Rgba { data: [0, 0, 0, 0] };
|
||||
let mut rgba = Rgba([0, 0, 0, 0]);
|
||||
rgba.apply_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(
|
||||
rgba,
|
||||
Rgba {
|
||||
data: [0, 0, 0, 0xFF]
|
||||
}
|
||||
);
|
||||
assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_with_alpha_bgra() {
|
||||
let mut bgra = Bgra { data: [0, 0, 0, 0] };
|
||||
let mut bgra = Bgra([0, 0, 0, 0]);
|
||||
bgra.apply_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(
|
||||
bgra,
|
||||
Bgra {
|
||||
data: [0, 0, 0, 0xFF]
|
||||
}
|
||||
);
|
||||
assert_eq!(bgra, Bgra([0, 0, 0, 0xFF]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_with_alpha_rgb() {
|
||||
let mut rgb = Rgb { data: [0, 0, 0] };
|
||||
let mut rgb = Rgb([0, 0, 0]);
|
||||
rgb.apply_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(rgb, Rgb { data: [0, 0, 0] });
|
||||
assert_eq!(rgb, Rgb([0, 0, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_with_alpha_bgr() {
|
||||
let mut bgr = Bgr { data: [0, 0, 0] };
|
||||
let mut bgr = Bgr([0, 0, 0]);
|
||||
bgr.apply_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(bgr, Bgr { data: [0, 0, 0] });
|
||||
assert_eq!(bgr, Bgr([0, 0, 0]));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_map_with_alpha_rgba() {
|
||||
let rgba = Rgba { data: [0, 0, 0, 0] }.map_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(
|
||||
rgba,
|
||||
Rgba {
|
||||
data: [0, 0, 0, 0xFF]
|
||||
}
|
||||
);
|
||||
let rgba = Rgba([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_with_alpha_rgb() {
|
||||
let rgb = Rgb { data: [0, 0, 0] }.map_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(rgb, Rgb { data: [0, 0, 0] });
|
||||
let rgb = Rgb([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(rgb, Rgb([0, 0, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_with_alpha_bgr() {
|
||||
let bgr = Bgr { data: [0, 0, 0] }.map_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(bgr, Bgr { data: [0, 0, 0] });
|
||||
let bgr = Bgr([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug"));
|
||||
assert_eq!(bgr, Bgr([0, 0, 0]));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_map_with_alpha_bgra() {
|
||||
let bgra = Bgra { data: [0, 0, 0, 0] }.map_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(
|
||||
bgra,
|
||||
Bgra {
|
||||
data: [0, 0, 0, 0xFF]
|
||||
}
|
||||
);
|
||||
let bgra = Bgra([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF);
|
||||
assert_eq!(bgra, Bgra([0, 0, 0, 0xFF]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blend_luma_alpha() {
|
||||
let ref mut a = LumaA {
|
||||
data: [255 as u8, 255],
|
||||
};
|
||||
let b = LumaA {
|
||||
data: [255 as u8, 255],
|
||||
};
|
||||
let ref mut a = LumaA([255 as u8, 255]);
|
||||
let b = LumaA([255 as u8, 255]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data[0], 255);
|
||||
assert_eq!(a.data[1], 255);
|
||||
assert_eq!(a.0[0], 255);
|
||||
assert_eq!(a.0[1], 255);
|
||||
|
||||
let ref mut a = LumaA {
|
||||
data: [255 as u8, 0],
|
||||
};
|
||||
let b = LumaA {
|
||||
data: [255 as u8, 255],
|
||||
};
|
||||
let ref mut a = LumaA([255 as u8, 0]);
|
||||
let b = LumaA([255 as u8, 255]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data[0], 255);
|
||||
assert_eq!(a.data[1], 255);
|
||||
assert_eq!(a.0[0], 255);
|
||||
assert_eq!(a.0[1], 255);
|
||||
|
||||
let ref mut a = LumaA {
|
||||
data: [255 as u8, 255],
|
||||
};
|
||||
let b = LumaA {
|
||||
data: [255 as u8, 0],
|
||||
};
|
||||
let ref mut a = LumaA([255 as u8, 255]);
|
||||
let b = LumaA([255 as u8, 0]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data[0], 255);
|
||||
assert_eq!(a.data[1], 255);
|
||||
assert_eq!(a.0[0], 255);
|
||||
assert_eq!(a.0[1], 255);
|
||||
|
||||
let ref mut a = LumaA {
|
||||
data: [255 as u8, 0],
|
||||
};
|
||||
let b = LumaA {
|
||||
data: [255 as u8, 0],
|
||||
};
|
||||
let ref mut a = LumaA([255 as u8, 0]);
|
||||
let b = LumaA([255 as u8, 0]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data[0], 255);
|
||||
assert_eq!(a.data[1], 0);
|
||||
assert_eq!(a.0[0], 255);
|
||||
assert_eq!(a.0[1], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blend_rgba() {
|
||||
let ref mut a = Rgba {
|
||||
data: [255 as u8, 255, 255, 255],
|
||||
};
|
||||
let b = Rgba {
|
||||
data: [255 as u8, 255, 255, 255],
|
||||
};
|
||||
let ref mut a = Rgba([255 as u8, 255, 255, 255]);
|
||||
let b = Rgba([255 as u8, 255, 255, 255]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data, [255, 255, 255, 255]);
|
||||
assert_eq!(a.0, [255, 255, 255, 255]);
|
||||
|
||||
let ref mut a = Rgba {
|
||||
data: [255 as u8, 255, 255, 0],
|
||||
};
|
||||
let b = Rgba {
|
||||
data: [255 as u8, 255, 255, 255],
|
||||
};
|
||||
let ref mut a = Rgba([255 as u8, 255, 255, 0]);
|
||||
let b = Rgba([255 as u8, 255, 255, 255]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data, [255, 255, 255, 255]);
|
||||
assert_eq!(a.0, [255, 255, 255, 255]);
|
||||
|
||||
let ref mut a = Rgba {
|
||||
data: [255 as u8, 255, 255, 255],
|
||||
};
|
||||
let b = Rgba {
|
||||
data: [255 as u8, 255, 255, 0],
|
||||
};
|
||||
let ref mut a = Rgba([255 as u8, 255, 255, 255]);
|
||||
let b = Rgba([255 as u8, 255, 255, 0]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data, [255, 255, 255, 255]);
|
||||
assert_eq!(a.0, [255, 255, 255, 255]);
|
||||
|
||||
let ref mut a = Rgba {
|
||||
data: [255 as u8, 255, 255, 0],
|
||||
};
|
||||
let b = Rgba {
|
||||
data: [255 as u8, 255, 255, 0],
|
||||
};
|
||||
let ref mut a = Rgba([255 as u8, 255, 255, 0]);
|
||||
let b = Rgba([255 as u8, 255, 255, 0]);
|
||||
a.blend(&b);
|
||||
assert_eq!(a.data, [255, 255, 255, 0]);
|
||||
assert_eq!(a.0, [255, 255, 255, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_without_alpha_rgba() {
|
||||
let mut rgba = Rgba([0, 0, 0, 0]);
|
||||
rgba.apply_without_alpha(|s| s + 1);
|
||||
assert_eq!(rgba, Rgba([1, 1, 1, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_without_alpha_bgra() {
|
||||
let mut bgra = Bgra([0, 0, 0, 0]);
|
||||
bgra.apply_without_alpha(|s| s + 1);
|
||||
assert_eq!(bgra, Bgra([1, 1, 1, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_without_alpha_rgb() {
|
||||
let mut rgb = Rgb([0, 0, 0]);
|
||||
rgb.apply_without_alpha(|s| s + 1);
|
||||
assert_eq!(rgb, Rgb([1, 1, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_without_alpha_bgr() {
|
||||
let mut bgr = Bgr([0, 0, 0]);
|
||||
bgr.apply_without_alpha(|s| s + 1);
|
||||
assert_eq!(bgr, Bgr([1, 1, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_without_alpha_rgba() {
|
||||
let rgba = Rgba([0, 0, 0, 0]).map_without_alpha(|s| s + 1);
|
||||
assert_eq!(rgba, Rgba([1, 1, 1, 0]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_without_alpha_rgb() {
|
||||
let rgb = Rgb([0, 0, 0]).map_without_alpha(|s| s + 1);
|
||||
assert_eq!(rgb, Rgb([1, 1, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_without_alpha_bgr() {
|
||||
let bgr = Bgr([0, 0, 0]).map_without_alpha(|s| s + 1);
|
||||
assert_eq!(bgr, Bgr([1, 1, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_without_alpha_bgra() {
|
||||
let bgra = Bgra([0, 0, 0, 0]).map_without_alpha(|s| s + 1);
|
||||
assert_eq!(bgra, Bgra([1, 1, 1, 0]));
|
||||
}
|
||||
}
|
||||
|
12
third_party/rust/image/src/dxt.rs
vendored
12
third_party/rust/image/src/dxt.rs
vendored
@ -83,9 +83,6 @@ impl<R: Read> DXTDecoder<R> {
|
||||
}
|
||||
let width_blocks = width / 4;
|
||||
let height_blocks = height / 4;
|
||||
if width.count_ones() != 1 || height.count_ones() != 1 {
|
||||
return Err(ImageError::DimensionError);
|
||||
}
|
||||
Ok(DXTDecoder {
|
||||
inner: r,
|
||||
width_blocks,
|
||||
@ -113,7 +110,7 @@ impl<R: Read> DXTDecoder<R> {
|
||||
|
||||
// Note that, due to the way that DXT compression works, a scanline is considered to consist out of
|
||||
// 4 lines of pixels.
|
||||
impl<R: Read> ImageDecoder for DXTDecoder<R> {
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for DXTDecoder<R> {
|
||||
type Reader = DXTReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
@ -152,7 +149,7 @@ impl<R: Read> ImageDecoder for DXTDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoderExt for DXTDecoder<R> {
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoderExt<'a> for DXTDecoder<R> {
|
||||
fn read_rect_with_progress<F: Fn(Progress)>(
|
||||
&mut self,
|
||||
x: u64,
|
||||
@ -216,9 +213,6 @@ impl<W: Write> DXTEncoder<W> {
|
||||
}
|
||||
let width_blocks = width / 4;
|
||||
let height_blocks = height / 4;
|
||||
if width.count_ones() != 1 || height.count_ones() != 1 {
|
||||
return Err(ImageError::DimensionError);
|
||||
}
|
||||
|
||||
let stride = variant.decoded_bytes_per_block();
|
||||
|
||||
@ -624,7 +618,7 @@ fn encode_dxt_colors(source: &[u8], dest: &mut [u8]) {
|
||||
swap(&mut color0, &mut color1);
|
||||
// Indexes are packed 2 bits wide, swap index 0/1 but preserve 2/3.
|
||||
let filter = (chosen_indices & 0xAAAA_AAAA) >> 1;
|
||||
chosen_indices ^= filter ^ 0x555_5555;
|
||||
chosen_indices ^= filter ^ 0x5555_5555;
|
||||
}
|
||||
} else if !chosen_use_0 {
|
||||
swap(&mut color0, &mut color1);
|
||||
|
153
third_party/rust/image/src/dynimage.rs
vendored
153
third_party/rust/image/src/dynimage.rs
vendored
@ -3,6 +3,7 @@ use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{BufRead, BufReader, BufWriter, Seek, Write};
|
||||
use std::path::Path;
|
||||
use std::u32;
|
||||
|
||||
#[cfg(feature = "bmp")]
|
||||
use bmp;
|
||||
@ -491,7 +492,7 @@ impl DynamicImage {
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
try!(p.encode(&bytes, width, height, color));
|
||||
p.encode(&bytes, width, height, color)?;
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(feature = "pnm")]
|
||||
@ -508,14 +509,14 @@ impl DynamicImage {
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
try!(p.encode(&bytes[..], width, height, color));
|
||||
p.encode(&bytes[..], width, height, color)?;
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(feature = "jpeg")]
|
||||
image::ImageOutputFormat::JPEG(quality) => {
|
||||
let mut j = jpeg::JPEGEncoder::new_with_quality(w, quality);
|
||||
|
||||
try!(j.encode(&bytes, width, height, color));
|
||||
j.encode(&bytes, width, height, color)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -535,14 +536,14 @@ impl DynamicImage {
|
||||
image::ImageOutputFormat::ICO => {
|
||||
let i = ico::ICOEncoder::new(w);
|
||||
|
||||
try!(i.encode(&bytes, width, height, color));
|
||||
i.encode(&bytes, width, height, color)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "bmp")]
|
||||
image::ImageOutputFormat::BMP => {
|
||||
let mut b = bmp::BMPEncoder::new(w);
|
||||
try!(b.encode(&bytes, width, height, color));
|
||||
b.encode(&bytes, width, height, color)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -563,6 +564,20 @@ impl DynamicImage {
|
||||
p.save(path)
|
||||
})
|
||||
}
|
||||
|
||||
/// Saves the buffer to a file at the specified path in
|
||||
/// the specified format.
|
||||
///
|
||||
/// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
|
||||
/// supported types.
|
||||
pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> io::Result<()>
|
||||
where
|
||||
Q: AsRef<Path>,
|
||||
{
|
||||
dynamic_map!(*self, ref p -> {
|
||||
p.save_with_format(path, format)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
@ -625,10 +640,10 @@ impl GenericImage for DynamicImage {
|
||||
}
|
||||
|
||||
/// Decodes an image and stores it into a dynamic image
|
||||
pub fn decoder_to_image<I: ImageDecoder>(codec: I) -> ImageResult<DynamicImage> {
|
||||
pub fn decoder_to_image<'a, I: ImageDecoder<'a>>(codec: I) -> ImageResult<DynamicImage> {
|
||||
let color = codec.colortype();
|
||||
let (w, h) = codec.dimensions();
|
||||
let buf = try!(codec.read_image());
|
||||
let buf = codec.read_image()?;
|
||||
|
||||
// TODO: Avoid this cast by having ImageBuffer use u64's
|
||||
assert!(w <= u32::max_value() as u64);
|
||||
@ -760,13 +775,67 @@ fn open_impl(path: &Path) -> ImageResult<DynamicImage> {
|
||||
load(fin, format)
|
||||
}
|
||||
|
||||
/// Read the dimensions of the image located at the specified path.
|
||||
/// This is faster than fully loading the image and then getting its dimensions.
|
||||
pub fn image_dimensions<P>(path: P) -> ImageResult<(u32, u32)>
|
||||
where
|
||||
P: AsRef<Path>
|
||||
{
|
||||
// thin wrapper function to strip generics before calling open_impl
|
||||
image_dimensions_impl(path.as_ref())
|
||||
}
|
||||
|
||||
fn image_dimensions_impl(path: &Path) -> ImageResult<(u32, u32)> {
|
||||
let fin = File::open(path)?;
|
||||
let fin = BufReader::new(fin);
|
||||
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.map_or("".to_string(), |s| s.to_ascii_lowercase());
|
||||
|
||||
let (w, h): (u64, u64) = match &ext[..] {
|
||||
#[cfg(feature = "jpeg")]
|
||||
"jpg" | "jpeg" => jpeg::JPEGDecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "png_codec")]
|
||||
"png" => png::PNGDecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "gif_codec")]
|
||||
"gif" => gif::Decoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "webp")]
|
||||
"webp" => webp::WebpDecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "tiff")]
|
||||
"tif" | "tiff" => tiff::TIFFDecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "tga")]
|
||||
"tga" => tga::TGADecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "bmp")]
|
||||
"bmp" => bmp::BMPDecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "ico")]
|
||||
"ico" => ico::ICODecoder::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "hdr")]
|
||||
"hdr" => hdr::HDRAdapter::new(fin)?.dimensions(),
|
||||
#[cfg(feature = "pnm")]
|
||||
"pbm" | "pam" | "ppm" | "pgm" => {
|
||||
pnm::PNMDecoder::new(fin)?.dimensions()
|
||||
}
|
||||
format => return Err(image::ImageError::UnsupportedError(format!(
|
||||
"Image format image/{:?} is not supported.",
|
||||
format
|
||||
))),
|
||||
};
|
||||
if w >= u32::MAX as u64 || h >= u32::MAX as u64 {
|
||||
return Err(image::ImageError::DimensionError);
|
||||
}
|
||||
Ok((w as u32, h as u32))
|
||||
}
|
||||
|
||||
|
||||
/// Saves the supplied buffer to a file at the path specified.
|
||||
///
|
||||
/// The image format is derived from the file extension. The buffer is assumed to have
|
||||
/// the correct format according to the specified color type.
|
||||
|
||||
/// This will lead to corrupted files if the buffer contains malformed data. Currently only
|
||||
/// jpeg and png files are supported.
|
||||
/// jpeg, png, ico, pnm, bmp and tiff files are supported.
|
||||
pub fn save_buffer<P>(
|
||||
path: P,
|
||||
buf: &[u8],
|
||||
@ -788,7 +857,7 @@ fn save_buffer_impl(
|
||||
height: u32,
|
||||
color: color::ColorType,
|
||||
) -> io::Result<()> {
|
||||
let fout = &mut BufWriter::new(try!(File::create(path)));
|
||||
let fout = &mut BufWriter::new(File::create(path)?);
|
||||
let ext = path.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
.map_or("".to_string(), |s| s.to_ascii_lowercase());
|
||||
@ -816,6 +885,9 @@ fn save_buffer_impl(
|
||||
"pam" => pnm::PNMEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "bmp")]
|
||||
"bmp" => bmp::BMPEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "tiff")]
|
||||
"tif" | "tiff" => tiff::TiffEncoder::new(fout).encode(buf, width, height, color)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e))), // FIXME: see https://github.com/image-rs/image/issues/921
|
||||
format => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
&format!("Unsupported image format image/{:?}", format)[..],
|
||||
@ -823,6 +895,59 @@ fn save_buffer_impl(
|
||||
}
|
||||
}
|
||||
|
||||
/// Saves the supplied buffer to a file at the path specified
|
||||
/// in the specified format.
|
||||
///
|
||||
/// The buffer is assumed to have the correct format according
|
||||
/// to the specified color type.
|
||||
/// This will lead to corrupted files if the buffer contains
|
||||
/// malformed data. Currently only jpeg, png, ico, bmp and
|
||||
/// tiff files are supported.
|
||||
pub fn save_buffer_with_format<P>(
|
||||
path: P,
|
||||
buf: &[u8],
|
||||
width: u32,
|
||||
height: u32,
|
||||
color: color::ColorType,
|
||||
format: ImageFormat,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// thin wrapper function to strip generics
|
||||
save_buffer_with_format_impl(path.as_ref(), buf, width, height, color, format)
|
||||
}
|
||||
|
||||
fn save_buffer_with_format_impl(
|
||||
path: &Path,
|
||||
buf: &[u8],
|
||||
width: u32,
|
||||
height: u32,
|
||||
color: color::ColorType,
|
||||
format: ImageFormat,
|
||||
) -> io::Result<()> {
|
||||
let fout = &mut BufWriter::new(File::create(path)?);
|
||||
|
||||
match format {
|
||||
#[cfg(feature = "ico")]
|
||||
image::ImageFormat::ICO => ico::ICOEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "jpeg")]
|
||||
image::ImageFormat::JPEG => jpeg::JPEGEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "png_codec")]
|
||||
image::ImageFormat::PNG => png::PNGEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "bmp")]
|
||||
image::ImageFormat::BMP => bmp::BMPEncoder::new(fout).encode(buf, width, height, color),
|
||||
#[cfg(feature = "tiff")]
|
||||
image::ImageFormat::TIFF => tiff::TiffEncoder::new(fout)
|
||||
.encode(buf, width, height, color)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e))),
|
||||
_ => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
&format!("Unsupported image format image/{:?}", format)[..],
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new image from a Reader
|
||||
pub fn load<R: BufRead + Seek>(r: R, format: ImageFormat) -> ImageResult<DynamicImage> {
|
||||
#[allow(deprecated, unreachable_patterns)]
|
||||
@ -860,7 +985,7 @@ static MAGIC_BYTES: [(&'static [u8], ImageFormat); 17] = [
|
||||
(&[0xff, 0xd8, 0xff], ImageFormat::JPEG),
|
||||
(b"GIF89a", ImageFormat::GIF),
|
||||
(b"GIF87a", ImageFormat::GIF),
|
||||
(b"WEBP", ImageFormat::WEBP),
|
||||
(b"RIFF", ImageFormat::WEBP), // TODO: better magic byte detection, see https://github.com/image-rs/image/issues/660
|
||||
(b"MM.*", ImageFormat::TIFF),
|
||||
(b"II*.", ImageFormat::TIFF),
|
||||
(b"BM", ImageFormat::BMP),
|
||||
@ -1033,4 +1158,12 @@ mod test {
|
||||
&[0b11110011, 0b00001100],
|
||||
vec![255, 0]);
|
||||
}
|
||||
|
||||
#[cfg(feature = "jpeg")]
|
||||
#[test]
|
||||
fn image_dimensions() {
|
||||
let im_path = "./tests/images/jpg/progressive/cat.jpg";
|
||||
let dims = super::image_dimensions(im_path).unwrap();
|
||||
assert_eq!(dims, (320, 240));
|
||||
}
|
||||
}
|
||||
|
32
third_party/rust/image/src/flat.rs
vendored
32
third_party/rust/image/src/flat.rs
vendored
@ -559,8 +559,8 @@ impl<Buffer> FlatSamples<Buffer> {
|
||||
pub fn as_view<P>(&self) -> Result<View<&[P::Subpixel], P>, Error>
|
||||
where P: Pixel, Buffer: AsRef<[P::Subpixel]>,
|
||||
{
|
||||
if self.layout.channels != P::channel_count() {
|
||||
return Err(Error::WrongColor(P::color_type()))
|
||||
if self.layout.channels != P::CHANNEL_COUNT {
|
||||
return Err(Error::WrongColor(P::COLOR_TYPE))
|
||||
}
|
||||
|
||||
let as_ref = self.samples.as_ref();
|
||||
@ -596,8 +596,8 @@ impl<Buffer> FlatSamples<Buffer> {
|
||||
pub fn as_view_with_mut_samples<P>(&mut self) -> Result<View<&mut [P::Subpixel], P>, Error>
|
||||
where P: Pixel, Buffer: AsMut<[P::Subpixel]>,
|
||||
{
|
||||
if self.layout.channels != P::channel_count() {
|
||||
return Err(Error::WrongColor(P::color_type()))
|
||||
if self.layout.channels != P::CHANNEL_COUNT {
|
||||
return Err(Error::WrongColor(P::COLOR_TYPE))
|
||||
}
|
||||
|
||||
let as_mut = self.samples.as_mut();
|
||||
@ -633,8 +633,8 @@ impl<Buffer> FlatSamples<Buffer> {
|
||||
return Err(Error::NormalFormRequired(NormalForm::PixelPacked))
|
||||
}
|
||||
|
||||
if self.layout.channels != P::channel_count() {
|
||||
return Err(Error::WrongColor(P::color_type()))
|
||||
if self.layout.channels != P::CHANNEL_COUNT {
|
||||
return Err(Error::WrongColor(P::COLOR_TYPE))
|
||||
}
|
||||
|
||||
let as_mut = self.samples.as_mut();
|
||||
@ -717,8 +717,8 @@ impl<Buffer> FlatSamples<Buffer> {
|
||||
return Err((Error::NormalFormRequired(NormalForm::RowMajorPacked), self))
|
||||
}
|
||||
|
||||
if self.layout.channels != P::channel_count() {
|
||||
return Err((Error::WrongColor(P::color_type()), self))
|
||||
if self.layout.channels != P::CHANNEL_COUNT {
|
||||
return Err((Error::WrongColor(P::COLOR_TYPE), self))
|
||||
}
|
||||
|
||||
if !self.fits(self.samples.deref().len()) {
|
||||
@ -1280,7 +1280,7 @@ impl<Buffer, P: Pixel> GenericImageView for View<Buffer, P>
|
||||
|
||||
let image = self.inner.samples.as_ref();
|
||||
let base_index = self.inner.in_bounds_index(0, x, y);
|
||||
let channels = P::channel_count() as usize;
|
||||
let channels = P::CHANNEL_COUNT as usize;
|
||||
|
||||
let mut buffer = [Zero::zero(); 256];
|
||||
buffer.iter_mut().enumerate().take(channels).for_each(|(c, to)| {
|
||||
@ -1325,7 +1325,7 @@ impl<Buffer, P: Pixel> GenericImageView for ViewMut<Buffer, P>
|
||||
|
||||
let image = self.inner.samples.as_ref();
|
||||
let base_index = self.inner.in_bounds_index(0, x, y);
|
||||
let channels = P::channel_count() as usize;
|
||||
let channels = P::CHANNEL_COUNT as usize;
|
||||
|
||||
let mut buffer = [Zero::zero(); 256];
|
||||
buffer.iter_mut().enumerate().take(channels).for_each(|(c, to)| {
|
||||
@ -1352,7 +1352,7 @@ impl<Buffer, P: Pixel> GenericImage for ViewMut<Buffer, P>
|
||||
}
|
||||
|
||||
let base_index = self.inner.in_bounds_index(0, x, y);
|
||||
let channel_count = <P as Pixel>::channel_count() as usize;
|
||||
let channel_count = <P as Pixel>::CHANNEL_COUNT as usize;
|
||||
let pixel_range = base_index..base_index + channel_count;
|
||||
P::from_slice_mut(&mut self.inner.samples.as_mut()[pixel_range])
|
||||
}
|
||||
@ -1461,12 +1461,10 @@ mod tests {
|
||||
{
|
||||
let mut view = buffer.as_view_mut::<LumaA<usize>>()
|
||||
.expect("This should be a valid mutable buffer");
|
||||
#[allow(deprecated)]
|
||||
let pixel_count = view.pixels_mut()
|
||||
.enumerate()
|
||||
.map(|(idx, (_, _, pixel))| *pixel = LumaA([2*idx, 2*idx + 1]))
|
||||
.count();
|
||||
assert_eq!(pixel_count, 9);
|
||||
assert_eq!(view.dimensions(), (3, 3));
|
||||
for i in 0..9 {
|
||||
*view.get_pixel_mut(i % 3, i / 3) = LumaA([2 * i as usize, 2 * i as usize + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
buffer.samples.iter()
|
||||
|
30
third_party/rust/image/src/gif.rs
vendored
30
third_party/rust/image/src/gif.rs
vendored
@ -30,7 +30,9 @@ extern crate gif;
|
||||
extern crate num_rational;
|
||||
|
||||
use std::clone::Clone;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use std::io::{self, Cursor, Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use self::gif::{ColorOutput, SetParameter};
|
||||
pub use self::gif::{DisposalMethod, Frame};
|
||||
@ -59,8 +61,24 @@ impl<R: Read> Decoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> ImageDecoder for Decoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct GifReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for GifReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for Decoder<R> {
|
||||
type Reader = GifReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.reader.width() as u64, self.reader.height() as u64)
|
||||
@ -71,7 +89,7 @@ impl<R: Read> ImageDecoder for Decoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(GifReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
@ -194,7 +212,7 @@ impl<R: Read> Iterator for GifFrameIterator<R> {
|
||||
// frame need to be used
|
||||
for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
|
||||
let previous_img_buffer = &self.non_disposed_frame;
|
||||
let mut adjusted_pixel: &mut Rgba<u8> = pixel;
|
||||
let adjusted_pixel: &mut Rgba<u8> = pixel;
|
||||
let previous_pixel: &Rgba<u8> = previous_img_buffer.get_pixel(x, y);
|
||||
|
||||
let pixel_alpha = adjusted_pixel.channels()[3];
|
||||
@ -262,7 +280,7 @@ impl<W: Write> Encoder<W> {
|
||||
result = encoder.write_frame(frame).map_err(|err| err.into());
|
||||
} else {
|
||||
let writer = self.w.take().unwrap();
|
||||
let mut encoder = try!(gif::Encoder::new(writer, frame.width, frame.height, &[]));
|
||||
let mut encoder = gif::Encoder::new(writer, frame.width, frame.height, &[])?;
|
||||
result = encoder.write_frame(&frame).map_err(|err| err.into());
|
||||
self.gif_encoder = Some(encoder);
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
use super::scoped_threadpool::Pool;
|
||||
use scoped_threadpool::Pool;
|
||||
use num_traits::cast::NumCast;
|
||||
use num_traits::identities::Zero;
|
||||
use std::mem;
|
||||
#[cfg(test)]
|
||||
use std::borrow::Cow;
|
||||
use std::error::Error;
|
||||
use std::io::{self, BufRead, Cursor, Seek};
|
||||
use std::io::{self, BufRead, Cursor, Read, Seek};
|
||||
use std::iter::Iterator;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::Path;
|
||||
use Primitive;
|
||||
|
||||
@ -24,7 +25,7 @@ pub struct HDRAdapter<R: BufRead> {
|
||||
impl<R: BufRead> HDRAdapter<R> {
|
||||
/// Creates adapter
|
||||
pub fn new(r: R) -> ImageResult<HDRAdapter<R>> {
|
||||
let decoder = try!(HDRDecoder::new(r));
|
||||
let decoder = HDRDecoder::new(r)?;
|
||||
let meta = decoder.metadata();
|
||||
Ok(HDRAdapter {
|
||||
inner: Some(decoder),
|
||||
@ -35,7 +36,7 @@ impl<R: BufRead> HDRAdapter<R> {
|
||||
|
||||
/// Allows reading old Radiance HDR images
|
||||
pub fn new_nonstrict(r: R) -> ImageResult<HDRAdapter<R>> {
|
||||
let decoder = try!(HDRDecoder::with_strictness(r, false));
|
||||
let decoder = HDRDecoder::with_strictness(r, false)?;
|
||||
let meta = decoder.metadata();
|
||||
Ok(HDRAdapter {
|
||||
inner: Some(decoder),
|
||||
@ -54,7 +55,7 @@ impl<R: BufRead> HDRAdapter<R> {
|
||||
let target = self.data.get_or_insert_with(|| Vec::with_capacity(len));
|
||||
target.clear();
|
||||
|
||||
for Rgb { data } in img {
|
||||
for Rgb(data) in img {
|
||||
target.extend_from_slice(&data);
|
||||
}
|
||||
|
||||
@ -66,8 +67,24 @@ impl<R: BufRead> HDRAdapter<R> {
|
||||
|
||||
}
|
||||
|
||||
impl<R: BufRead> ImageDecoder for HDRAdapter<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct HdrReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for HdrReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + BufRead> ImageDecoder<'a> for HDRAdapter<R> {
|
||||
type Reader = HdrReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.meta.width as u64, self.meta.height as u64)
|
||||
@ -78,7 +95,7 @@ impl<R: BufRead> ImageDecoder for HDRAdapter<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(HdrReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
@ -91,7 +108,7 @@ impl<R: BufRead> ImageDecoder for HDRAdapter<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead + Seek> ImageDecoderExt for HDRAdapter<R> {
|
||||
impl<'a, R: 'a + BufRead + Seek> ImageDecoderExt<'a> for HDRAdapter<R> {
|
||||
fn read_rect_with_progress<F: Fn(Progress)>(
|
||||
&mut self,
|
||||
x: u64,
|
||||
@ -128,7 +145,7 @@ pub struct HDRDecoder<R> {
|
||||
|
||||
/// Refer to [wikipedia](https://en.wikipedia.org/wiki/RGBE_image_format)
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct RGBE8Pixel {
|
||||
/// Color components
|
||||
pub c: [u8; 3],
|
||||
@ -180,7 +197,7 @@ impl RGBE8Pixel {
|
||||
/// Panics when scale or gamma is NaN
|
||||
#[inline]
|
||||
pub fn to_ldr_scale_gamma<T: Primitive + Zero>(self, scale: f32, gamma: f32) -> Rgb<T> {
|
||||
let Rgb { data } = self.to_hdr();
|
||||
let Rgb(data) = self.to_hdr();
|
||||
let (r, g, b) = (data[0], data[1], data[2]);
|
||||
#[inline]
|
||||
fn sg<T: Primitive + Zero>(v: f32, scale: f32, gamma: f32) -> T {
|
||||
@ -229,21 +246,21 @@ impl<R: BufRead> HDRDecoder<R> {
|
||||
let r = &mut reader;
|
||||
if strict {
|
||||
let mut signature = [0; SIGNATURE_LENGTH];
|
||||
try!(r.read_exact(&mut signature));
|
||||
r.read_exact(&mut signature)?;
|
||||
if signature != SIGNATURE {
|
||||
return Err(ImageError::FormatError(
|
||||
"Radiance HDR signature not found".to_string(),
|
||||
));
|
||||
} // no else
|
||||
// skip signature line ending
|
||||
try!(read_line_u8(r));
|
||||
read_line_u8(r)?;
|
||||
} else {
|
||||
// Old Radiance HDR files (*.pic) don't use signature
|
||||
// Let them be parsed in non-strict mode
|
||||
}
|
||||
// read header data until empty line
|
||||
loop {
|
||||
match try!(read_line_u8(r)) {
|
||||
match read_line_u8(r)? {
|
||||
None => {
|
||||
// EOF before end of header
|
||||
return Err(ImageError::FormatError("EOF in header".into()));
|
||||
@ -259,20 +276,20 @@ impl<R: BufRead> HDRDecoder<R> {
|
||||
} // no else
|
||||
// process attribute line
|
||||
let line = String::from_utf8_lossy(&line[..]);
|
||||
try!(attributes.update_header_info(&line, strict));
|
||||
attributes.update_header_info(&line, strict)?;
|
||||
} // <= Some(line)
|
||||
} // match read_line_u8()
|
||||
} // loop
|
||||
} // scope to end borrow of reader
|
||||
// parse dimensions
|
||||
let (width, height) = match try!(read_line_u8(&mut reader)) {
|
||||
let (width, height) = match read_line_u8(&mut reader)? {
|
||||
None => {
|
||||
// EOF instead of image dimensions
|
||||
return Err(ImageError::FormatError("EOF in dimensions line".into()));
|
||||
}
|
||||
Some(dimensions) => {
|
||||
let dimensions = String::from_utf8_lossy(&dimensions[..]);
|
||||
try!(parse_dimensions_line(&dimensions, strict))
|
||||
parse_dimensions_line(&dimensions, strict)?
|
||||
}
|
||||
};
|
||||
|
||||
@ -302,13 +319,9 @@ impl<R: BufRead> HDRDecoder<R> {
|
||||
}
|
||||
// expression self.width > 0 && self.height > 0 is true from now to the end of this method
|
||||
let pixel_count = self.width as usize * self.height as usize;
|
||||
let mut ret = Vec::<RGBE8Pixel>::with_capacity(pixel_count);
|
||||
unsafe {
|
||||
// RGBE8Pixel doesn't implement Drop, so it's Ok to drop half-initialized ret
|
||||
ret.set_len(pixel_count);
|
||||
} // ret contains uninitialized data, so now it's my responsibility to return fully initialized ret
|
||||
let mut ret = vec![Default::default(); pixel_count];
|
||||
for chunk in ret.chunks_mut(self.width as usize) {
|
||||
try!(read_scanline(&mut self.r, chunk));
|
||||
read_scanline(&mut self.r, chunk)?;
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
@ -317,57 +330,48 @@ impl<R: BufRead> HDRDecoder<R> {
|
||||
pub fn read_image_transform<T: Send, F: Send + Sync + Fn(RGBE8Pixel) -> T>(
|
||||
mut self,
|
||||
f: F,
|
||||
) -> ImageResult<Vec<T>> {
|
||||
output_slice: &mut [T],
|
||||
) -> ImageResult<()> {
|
||||
assert_eq!(output_slice.len(), self.width as usize * self.height as usize);
|
||||
|
||||
// Don't read anything if image is empty
|
||||
if self.width == 0 || self.height == 0 {
|
||||
return Ok(vec![]);
|
||||
return Ok(());
|
||||
}
|
||||
// expression self.width > 0 && self.height > 0 is true from now to the end of this method
|
||||
// scanline buffer
|
||||
let uszwidth = self.width as usize;
|
||||
|
||||
let pixel_count = self.width as usize * self.height as usize;
|
||||
let mut ret = Vec::with_capacity(pixel_count);
|
||||
unsafe {
|
||||
// RGBE8Pixel doesn't implement Drop, so it's Ok to drop half-initialized ret
|
||||
ret.set_len(pixel_count);
|
||||
} // ret contains uninitialized data, so now it's my responsibility to return fully initialized ret
|
||||
let chunks_iter = output_slice.chunks_mut(self.width as usize);
|
||||
let mut pool = Pool::new(8); //
|
||||
|
||||
{
|
||||
let chunks_iter = ret.chunks_mut(uszwidth);
|
||||
let mut pool = Pool::new(8); //
|
||||
|
||||
try!(pool.scoped(|scope| {
|
||||
for chunk in chunks_iter {
|
||||
let mut buf = Vec::<RGBE8Pixel>::with_capacity(uszwidth);
|
||||
unsafe {
|
||||
buf.set_len(uszwidth);
|
||||
try!(pool.scoped(|scope| {
|
||||
for chunk in chunks_iter {
|
||||
let mut buf = vec![Default::default(); self.width as usize];
|
||||
read_scanline(&mut self.r, &mut buf[..])?;
|
||||
let f = &f;
|
||||
scope.execute(move || {
|
||||
for (dst, &pix) in chunk.iter_mut().zip(buf.iter()) {
|
||||
*dst = f(pix);
|
||||
}
|
||||
try!(read_scanline(&mut self.r, &mut buf[..]));
|
||||
let f = &f;
|
||||
scope.execute(move || {
|
||||
for (dst, &pix) in chunk.iter_mut().zip(buf.iter()) {
|
||||
*dst = f(pix);
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}) as Result<(), ImageError>);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}) as Result<(), ImageError>);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consumes decoder and returns a vector of Rgb<u8> pixels.
|
||||
/// scale = 1, gamma = 2.2
|
||||
pub fn read_image_ldr(self) -> ImageResult<Vec<Rgb<u8>>> {
|
||||
self.read_image_transform(|pix| pix.to_ldr())
|
||||
let mut ret = vec![Rgb([0,0,0]); self.width as usize * self.height as usize];
|
||||
self.read_image_transform(|pix| pix.to_ldr(), &mut ret[..])?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Consumes decoder and returns a vector of Rgb<f32> pixels.
|
||||
///
|
||||
pub fn read_image_hdr(self) -> ImageResult<Vec<Rgb<f32>>> {
|
||||
self.read_image_transform(|pix| pix.to_hdr())
|
||||
let mut ret = vec![Rgb([0.0, 0.0, 0.0]); self.width as usize * self.height as usize];
|
||||
self.read_image_transform(|pix| pix.to_hdr(), &mut ret[..])?;
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,17 +380,10 @@ impl<R: BufRead> IntoIterator for HDRDecoder<R> {
|
||||
type IntoIter = HDRImageDecoderIterator<R>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
// scanline buffer
|
||||
let mut buf = Vec::with_capacity(self.width as usize);
|
||||
unsafe {
|
||||
// dropping half-initialized vector of RGBE8Pixel is safe
|
||||
// and I took care to hide half-initialized vector from a user
|
||||
buf.set_len(self.width as usize);
|
||||
}
|
||||
HDRImageDecoderIterator {
|
||||
r: self.r,
|
||||
scanline_cnt: self.height as usize,
|
||||
buf,
|
||||
buf: vec![Default::default(); self.width as usize],
|
||||
col: 0,
|
||||
scanline: 0,
|
||||
trouble: true, // make first call to `next()` read scanline
|
||||
@ -475,18 +472,18 @@ fn read_scanline<R: BufRead>(r: &mut R, buf: &mut [RGBE8Pixel]) -> ImageResult<(
|
||||
assert!(!buf.is_empty());
|
||||
let width = buf.len();
|
||||
// first 4 bytes in scanline allow to determine compression method
|
||||
let fb = try!(read_rgbe(r));
|
||||
let fb = read_rgbe(r)?;
|
||||
if fb.c[0] == 2 && fb.c[1] == 2 && fb.c[2] < 128 {
|
||||
// denormalized pixel value (2,2,<128,_) indicates new per component RLE method
|
||||
// decode_component guarantees that offset is within 0 .. width
|
||||
// therefore we can skip bounds checking here, but we will not
|
||||
try!(decode_component(r, width, |offset, value| buf[offset].c[0] = value));
|
||||
try!(decode_component(r, width, |offset, value| buf[offset].c[1] = value));
|
||||
try!(decode_component(r, width, |offset, value| buf[offset].c[2] = value));
|
||||
try!(decode_component(r, width, |offset, value| buf[offset].e = value));
|
||||
decode_component(r, width, |offset, value| buf[offset].c[0] = value)?;
|
||||
decode_component(r, width, |offset, value| buf[offset].c[1] = value)?;
|
||||
decode_component(r, width, |offset, value| buf[offset].c[2] = value)?;
|
||||
decode_component(r, width, |offset, value| buf[offset].e = value)?;
|
||||
} else {
|
||||
// old RLE method (it was considered old around 1991, should it be here?)
|
||||
try!(decode_old_rle(r, fb, buf));
|
||||
decode_old_rle(r, fb, buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -494,7 +491,7 @@ fn read_scanline<R: BufRead>(r: &mut R, buf: &mut [RGBE8Pixel]) -> ImageResult<(
|
||||
#[inline(always)]
|
||||
fn read_byte<R: BufRead>(r: &mut R) -> io::Result<u8> {
|
||||
let mut buf = [0u8];
|
||||
try!(r.read_exact(&mut buf[..]));
|
||||
r.read_exact(&mut buf[..])?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
|
||||
@ -510,7 +507,7 @@ fn decode_component<R: BufRead, S: FnMut(usize, u8)>(
|
||||
while pos < width {
|
||||
// increment position by a number of decompressed values
|
||||
pos += {
|
||||
let rl = try!(read_byte(r));
|
||||
let rl = read_byte(r)?;
|
||||
if rl <= 128 {
|
||||
// sanity check
|
||||
if pos + rl as usize > width {
|
||||
@ -519,7 +516,7 @@ fn decode_component<R: BufRead, S: FnMut(usize, u8)>(
|
||||
));
|
||||
}
|
||||
// read values
|
||||
try!(r.read_exact(&mut buf[0..rl as usize]));
|
||||
r.read_exact(&mut buf[0..rl as usize])?;
|
||||
for (offset, &value) in buf[0..rl as usize].iter().enumerate() {
|
||||
set_component(pos + offset, value);
|
||||
}
|
||||
@ -534,7 +531,7 @@ fn decode_component<R: BufRead, S: FnMut(usize, u8)>(
|
||||
));
|
||||
}
|
||||
// fill with same value
|
||||
let value = try!(read_byte(r));
|
||||
let value = read_byte(r)?;
|
||||
for offset in 0..rl as usize {
|
||||
set_component(pos + offset, value);
|
||||
}
|
||||
@ -583,7 +580,7 @@ fn decode_old_rle<R: BufRead>(
|
||||
let mut rl_mult = 1; // current run length multiplier
|
||||
let mut prev_pixel = fb;
|
||||
while x_off < width {
|
||||
let pix = try!(read_rgbe(r));
|
||||
let pix = read_rgbe(r)?;
|
||||
// it's harder to forget to increase x_off if I write this this way.
|
||||
x_off += {
|
||||
if let Some(rl) = rl_marker(pix) {
|
||||
@ -619,7 +616,7 @@ fn decode_old_rle<R: BufRead>(
|
||||
|
||||
fn read_rgbe<R: BufRead>(r: &mut R) -> io::Result<RGBE8Pixel> {
|
||||
let mut buf = [0u8; 4];
|
||||
try!(r.read_exact(&mut buf[..]));
|
||||
r.read_exact(&mut buf[..])?;
|
||||
Ok(RGBE8Pixel {c: [buf[0], buf[1], buf[2]], e: buf[3] })
|
||||
}
|
||||
|
||||
@ -808,8 +805,8 @@ fn parse_dimensions_line(line: &str, strict: bool) -> ImageResult<(u32, u32)> {
|
||||
("-Y", "+X") => {
|
||||
// Common orientation (left-right, top-down)
|
||||
// c1_str is height, c2_str is width
|
||||
let height = try!(c1_str.parse::<u32>().into_image_error(err));
|
||||
let width = try!(c2_str.parse::<u32>().into_image_error(err));
|
||||
let height = c1_str.parse::<u32>().into_image_error(err)?;
|
||||
let width = c2_str.parse::<u32>().into_image_error(err)?;
|
||||
Ok((width, height))
|
||||
}
|
||||
_ => Err(ImageError::FormatError(format!(
|
||||
@ -920,17 +917,17 @@ pub fn read_raw_file<P: AsRef<Path>>(path: P) -> ::std::io::Result<Vec<Rgb<f32>>
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
||||
let mut r = BufReader::new(try!(File::open(path)));
|
||||
let w = try!(r.read_u32::<LE>()) as usize;
|
||||
let h = try!(r.read_u32::<LE>()) as usize;
|
||||
let c = try!(r.read_u32::<LE>()) as usize;
|
||||
let mut r = BufReader::new(File::open(path)?);
|
||||
let w = r.read_u32::<LE>()? as usize;
|
||||
let h = r.read_u32::<LE>()? as usize;
|
||||
let c = r.read_u32::<LE>()? as usize;
|
||||
assert_eq!(c, 3);
|
||||
let cnt = w * h;
|
||||
let mut ret = Vec::with_capacity(cnt);
|
||||
for _ in 0..cnt {
|
||||
let cr = try!(r.read_f32::<LE>());
|
||||
let cg = try!(r.read_f32::<LE>());
|
||||
let cb = try!(r.read_f32::<LE>());
|
||||
let cr = r.read_f32::<LE>()?;
|
||||
let cg = r.read_f32::<LE>()?;
|
||||
let cb = r.read_f32::<LE>()?;
|
||||
ret.push(Rgb([cr, cg, cb]));
|
||||
}
|
||||
Ok(ret)
|
@ -18,15 +18,15 @@ impl<W: Write> HDREncoder<W> {
|
||||
pub fn encode(mut self, data: &[Rgb<f32>], width: usize, height: usize) -> Result<()> {
|
||||
assert!(data.len() >= width * height);
|
||||
let w = &mut self.w;
|
||||
try!(w.write_all(SIGNATURE));
|
||||
try!(w.write_all(b"\n"));
|
||||
try!(w.write_all(b"# Rust HDR encoder\n"));
|
||||
try!(w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n"));
|
||||
try!(w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes()));
|
||||
w.write_all(SIGNATURE)?;
|
||||
w.write_all(b"\n")?;
|
||||
w.write_all(b"# Rust HDR encoder\n")?;
|
||||
w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n")?;
|
||||
w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes())?;
|
||||
|
||||
if width < 8 || width > 32_768 {
|
||||
for &pix in data {
|
||||
try!(write_rgbe8(w, to_rgbe8(pix)));
|
||||
write_rgbe8(w, to_rgbe8(pix))?;
|
||||
}
|
||||
} else {
|
||||
// new RLE marker contains scanline width
|
||||
@ -54,19 +54,19 @@ impl<W: Write> HDREncoder<W> {
|
||||
*b = cp.c[2];
|
||||
*e = cp.e;
|
||||
}
|
||||
try!(write_rgbe8(w, marker)); // New RLE encoding marker
|
||||
write_rgbe8(w, marker)?; // New RLE encoding marker
|
||||
rle_buf.clear();
|
||||
rle_compress(&bufr[..], &mut rle_buf);
|
||||
try!(w.write_all(&rle_buf[..]));
|
||||
w.write_all(&rle_buf[..])?;
|
||||
rle_buf.clear();
|
||||
rle_compress(&bufg[..], &mut rle_buf);
|
||||
try!(w.write_all(&rle_buf[..]));
|
||||
w.write_all(&rle_buf[..])?;
|
||||
rle_buf.clear();
|
||||
rle_compress(&bufb[..], &mut rle_buf);
|
||||
try!(w.write_all(&rle_buf[..]));
|
||||
w.write_all(&rle_buf[..])?;
|
||||
rle_buf.clear();
|
||||
rle_compress(&bufe[..], &mut rle_buf);
|
||||
try!(w.write_all(&rle_buf[..]));
|
||||
w.write_all(&rle_buf[..])?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -226,7 +226,7 @@ fn write_rgbe8<W: Write>(w: &mut W, v: RGBE8Pixel) -> Result<()> {
|
||||
|
||||
/// Converts ```Rgb<f32>``` into ```RGBE8Pixel```
|
||||
pub fn to_rgbe8(pix: Rgb<f32>) -> RGBE8Pixel {
|
||||
let pix = pix.data;
|
||||
let pix = pix.0;
|
||||
let mx = f32::max(pix[0], f32::max(pix[1], pix[2]));
|
||||
if mx <= 0.0 {
|
||||
RGBE8Pixel { c: [0, 0, 0], e: 0 }
|
||||
@ -274,13 +274,13 @@ fn to_rgbe8_test() {
|
||||
}
|
||||
fn relative_dist(a: Rgb<f32>, b: Rgb<f32>) -> f32 {
|
||||
// maximal difference divided by maximal value
|
||||
let max_diff = a.data
|
||||
let max_diff = a.0
|
||||
.iter()
|
||||
.zip(b.data.iter())
|
||||
.zip(b.0.iter())
|
||||
.fold(0.0, |diff, (&a, &b)| f32::max(diff, (a - b).abs()));
|
||||
let max_val = a.data
|
||||
let max_val = a.0
|
||||
.iter()
|
||||
.chain(b.data.iter())
|
||||
.chain(b.0.iter())
|
||||
.fold(0.0, |maxv, &a| f32::max(maxv, a));
|
||||
if max_val == 0.0 {
|
||||
0.0
|
10
third_party/rust/image/src/hdr/mod.rs
vendored
10
third_party/rust/image/src/hdr/mod.rs
vendored
@ -8,10 +8,8 @@
|
||||
//! * <http://www.graphics.cornell.edu/~bjw/rgbe/rgbe.c>
|
||||
//!
|
||||
|
||||
extern crate scoped_threadpool;
|
||||
mod decoder;
|
||||
mod encoder;
|
||||
|
||||
mod hdr_decoder;
|
||||
mod hdr_encoder;
|
||||
|
||||
pub use self::hdr_decoder::*;
|
||||
pub use self::hdr_encoder::*;
|
||||
pub use self::decoder::*;
|
||||
pub use self::encoder::*;
|
||||
|
70
third_party/rust/image/src/ico/decoder.rs
vendored
70
third_party/rust/image/src/ico/decoder.rs
vendored
@ -1,5 +1,7 @@
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom};
|
||||
use std::io::{self, Cursor, Read, Seek, SeekFrom};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use color::ColorType;
|
||||
use image::{ImageDecoder, ImageError, ImageResult};
|
||||
@ -40,9 +42,9 @@ struct DirEntry {
|
||||
impl<R: Read + Seek> ICODecoder<R> {
|
||||
/// Create a new decoder that decodes from the stream ```r```
|
||||
pub fn new(mut r: R) -> ImageResult<ICODecoder<R>> {
|
||||
let entries = try!(read_entries(&mut r));
|
||||
let entry = try!(best_entry(entries));
|
||||
let decoder = try!(entry.decoder(r));
|
||||
let entries = read_entries(&mut r)?;
|
||||
let entry = best_entry(entries)?;
|
||||
let decoder = entry.decoder(r)?;
|
||||
|
||||
Ok(ICODecoder {
|
||||
selected_entry: entry,
|
||||
@ -52,24 +54,24 @@ impl<R: Read + Seek> ICODecoder<R> {
|
||||
}
|
||||
|
||||
fn read_entries<R: Read>(r: &mut R) -> ImageResult<Vec<DirEntry>> {
|
||||
let _reserved = try!(r.read_u16::<LittleEndian>());
|
||||
let _type = try!(r.read_u16::<LittleEndian>());
|
||||
let count = try!(r.read_u16::<LittleEndian>());
|
||||
let _reserved = r.read_u16::<LittleEndian>()?;
|
||||
let _type = r.read_u16::<LittleEndian>()?;
|
||||
let count = r.read_u16::<LittleEndian>()?;
|
||||
(0..count).map(|_| read_entry(r)).collect()
|
||||
}
|
||||
|
||||
fn read_entry<R: Read>(r: &mut R) -> ImageResult<DirEntry> {
|
||||
let mut entry = DirEntry::default();
|
||||
|
||||
entry.width = try!(r.read_u8());
|
||||
entry.height = try!(r.read_u8());
|
||||
entry.color_count = try!(r.read_u8());
|
||||
entry.width = r.read_u8()?;
|
||||
entry.height = r.read_u8()?;
|
||||
entry.color_count = r.read_u8()?;
|
||||
// Reserved value (not used)
|
||||
entry.reserved = try!(r.read_u8());
|
||||
entry.reserved = r.read_u8()?;
|
||||
|
||||
// This may be either the number of color planes (0 or 1), or the horizontal coordinate
|
||||
// of the hotspot for CUR files.
|
||||
entry.num_color_planes = try!(r.read_u16::<LittleEndian>());
|
||||
entry.num_color_planes = r.read_u16::<LittleEndian>()?;
|
||||
if entry.num_color_planes > 256 {
|
||||
return Err(ImageError::FormatError(
|
||||
"ICO image entry has a too large color planes/hotspot value".to_string(),
|
||||
@ -78,22 +80,22 @@ fn read_entry<R: Read>(r: &mut R) -> ImageResult<DirEntry> {
|
||||
|
||||
// This may be either the bit depth (may be 0 meaning unspecified),
|
||||
// or the vertical coordinate of the hotspot for CUR files.
|
||||
entry.bits_per_pixel = try!(r.read_u16::<LittleEndian>());
|
||||
entry.bits_per_pixel = r.read_u16::<LittleEndian>()?;
|
||||
if entry.bits_per_pixel > 256 {
|
||||
return Err(ImageError::FormatError(
|
||||
"ICO image entry has a too large bits per pixel/hotspot value".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
entry.image_length = try!(r.read_u32::<LittleEndian>());
|
||||
entry.image_offset = try!(r.read_u32::<LittleEndian>());
|
||||
entry.image_length = r.read_u32::<LittleEndian>()?;
|
||||
entry.image_offset = r.read_u32::<LittleEndian>()?;
|
||||
|
||||
Ok(entry)
|
||||
}
|
||||
|
||||
/// Find the entry with the highest (color depth, size).
|
||||
fn best_entry(mut entries: Vec<DirEntry>) -> ImageResult<DirEntry> {
|
||||
let mut best = try!(entries.pop().ok_or(ImageError::ImageEnd));
|
||||
let mut best = entries.pop().ok_or(ImageError::ImageEnd)?;
|
||||
let mut best_score = (
|
||||
best.bits_per_pixel,
|
||||
u32::from(best.real_width()) * u32::from(best.real_height()),
|
||||
@ -132,23 +134,23 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
fn seek_to_start<R: Read + Seek>(&self, r: &mut R) -> ImageResult<()> {
|
||||
try!(r.seek(SeekFrom::Start(u64::from(self.image_offset))));
|
||||
r.seek(SeekFrom::Start(u64::from(self.image_offset)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_png<R: Read + Seek>(&self, r: &mut R) -> ImageResult<bool> {
|
||||
try!(self.seek_to_start(r));
|
||||
self.seek_to_start(r)?;
|
||||
|
||||
// Read the first 8 bytes to sniff the image.
|
||||
let mut signature = [0u8; 8];
|
||||
try!(r.read_exact(&mut signature));
|
||||
r.read_exact(&mut signature)?;
|
||||
|
||||
Ok(signature == PNG_SIGNATURE)
|
||||
}
|
||||
|
||||
fn decoder<R: Read + Seek>(&self, mut r: R) -> ImageResult<InnerDecoder<R>> {
|
||||
let is_png = try!(self.is_png(&mut r));
|
||||
try!(self.seek_to_start(&mut r));
|
||||
let is_png = self.is_png(&mut r)?;
|
||||
self.seek_to_start(&mut r)?;
|
||||
|
||||
if is_png {
|
||||
Ok(PNG(PNGDecoder::new(r)?))
|
||||
@ -158,8 +160,24 @@ impl DirEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoder for ICODecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct IcoReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for IcoReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for ICODecoder<R> {
|
||||
type Reader = IcoReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
match self.inner_decoder {
|
||||
@ -176,7 +194,7 @@ impl<R: Read + Seek> ImageDecoder for ICODecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(IcoReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(self) -> ImageResult<Vec<u8>> {
|
||||
@ -227,7 +245,7 @@ impl<R: Read + Seek> ImageDecoder for ICODecoder<R> {
|
||||
|
||||
// If there's an AND mask following the image, read and apply it.
|
||||
let r = decoder.reader();
|
||||
let mask_start = try!(r.seek(SeekFrom::Current(0)));
|
||||
let mask_start = r.seek(SeekFrom::Current(0))?;
|
||||
let mask_end =
|
||||
u64::from(self.selected_entry.image_offset + self.selected_entry.image_length);
|
||||
let mask_length = mask_end - mask_start;
|
||||
@ -244,7 +262,7 @@ impl<R: Read + Seek> ImageDecoder for ICODecoder<R> {
|
||||
let mut x = 0;
|
||||
for _ in 0..mask_row_bytes {
|
||||
// Apply the bits of each byte until we reach the end of the row.
|
||||
let mask_byte = try!(r.read_u8());
|
||||
let mask_byte = r.read_u8()?;
|
||||
for bit in (0..8).rev() {
|
||||
if x >= width {
|
||||
break;
|
||||
|
28
third_party/rust/image/src/ico/encoder.rs
vendored
28
third_party/rust/image/src/ico/encoder.rs
vendored
@ -34,9 +34,9 @@ impl<W: Write> ICOEncoder<W> {
|
||||
color: ColorType,
|
||||
) -> io::Result<()> {
|
||||
let mut image_data: Vec<u8> = Vec::new();
|
||||
try!(PNGEncoder::new(&mut image_data).encode(data, width, height, color));
|
||||
PNGEncoder::new(&mut image_data).encode(data, width, height, color)?;
|
||||
|
||||
try!(write_icondir(&mut self.w, 1));
|
||||
write_icondir(&mut self.w, 1)?;
|
||||
try!(write_direntry(
|
||||
&mut self.w,
|
||||
width,
|
||||
@ -45,18 +45,18 @@ impl<W: Write> ICOEncoder<W> {
|
||||
ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
|
||||
image_data.len() as u32
|
||||
));
|
||||
try!(self.w.write_all(&image_data));
|
||||
self.w.write_all(&image_data)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
|
||||
// Reserved field (must be zero):
|
||||
try!(w.write_u16::<LittleEndian>(0));
|
||||
w.write_u16::<LittleEndian>(0)?;
|
||||
// Image type (ICO or CUR):
|
||||
try!(w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE));
|
||||
w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
|
||||
// Number of images in the file:
|
||||
try!(w.write_u16::<LittleEndian>(num_images));
|
||||
w.write_u16::<LittleEndian>(num_images)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -69,20 +69,20 @@ fn write_direntry<W: Write>(
|
||||
data_size: u32,
|
||||
) -> io::Result<()> {
|
||||
// Image dimensions:
|
||||
try!(write_width_or_height(w, width));
|
||||
try!(write_width_or_height(w, height));
|
||||
write_width_or_height(w, width)?;
|
||||
write_width_or_height(w, height)?;
|
||||
// Number of colors in palette (or zero for no palette):
|
||||
try!(w.write_u8(0));
|
||||
w.write_u8(0)?;
|
||||
// Reserved field (must be zero):
|
||||
try!(w.write_u8(0));
|
||||
w.write_u8(0)?;
|
||||
// Color planes:
|
||||
try!(w.write_u16::<LittleEndian>(0));
|
||||
w.write_u16::<LittleEndian>(0)?;
|
||||
// Bits per pixel:
|
||||
try!(w.write_u16::<LittleEndian>(bits_per_pixel(color) as u16));
|
||||
w.write_u16::<LittleEndian>(bits_per_pixel(color) as u16)?;
|
||||
// Image data size, in bytes:
|
||||
try!(w.write_u32::<LittleEndian>(data_size));
|
||||
w.write_u32::<LittleEndian>(data_size)?;
|
||||
// Image data offset, in bytes:
|
||||
try!(w.write_u32::<LittleEndian>(data_start));
|
||||
w.write_u32::<LittleEndian>(data_start)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
98
third_party/rust/image/src/image.rs
vendored
98
third_party/rust/image/src/image.rs
vendored
@ -2,7 +2,6 @@ use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use buffer::{ImageBuffer, Pixel};
|
||||
@ -90,7 +89,7 @@ impl Error for ImageError {
|
||||
}
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
fn cause(&self) -> Option<&dyn Error> {
|
||||
match *self {
|
||||
ImageError::IoError(ref e) => Some(e),
|
||||
_ => None,
|
||||
@ -264,12 +263,12 @@ impl ImageReadBuffer {
|
||||
|
||||
/// Decodes a specific region of the image, represented by the rectangle
|
||||
/// starting from ```x``` and ```y``` and having ```length``` and ```width```
|
||||
pub(crate) fn load_rect<D, F, F1, F2>(x: u64, y: u64, width: u64, height: u64, buf: &mut [u8],
|
||||
progress_callback: F,
|
||||
decoder: &mut D,
|
||||
mut seek_scanline: F1,
|
||||
mut read_scanline: F2) -> ImageResult<()>
|
||||
where D: ImageDecoder,
|
||||
pub(crate) fn load_rect<'a, D, F, F1, F2>(x: u64, y: u64, width: u64, height: u64, buf: &mut [u8],
|
||||
progress_callback: F,
|
||||
decoder: &mut D,
|
||||
mut seek_scanline: F1,
|
||||
mut read_scanline: F2) -> ImageResult<()>
|
||||
where D: ImageDecoder<'a>,
|
||||
F: Fn(Progress),
|
||||
F1: FnMut(&mut D, u64) -> io::Result<()>,
|
||||
F2: FnMut(&mut D, &mut [u8]) -> io::Result<usize>
|
||||
@ -359,9 +358,9 @@ pub struct Progress {
|
||||
}
|
||||
|
||||
/// The trait that all decoders implement
|
||||
pub trait ImageDecoder: Sized {
|
||||
pub trait ImageDecoder<'a>: Sized {
|
||||
/// The type of reader produced by `into_reader`.
|
||||
type Reader: Read;
|
||||
type Reader: Read + 'a;
|
||||
|
||||
/// Returns a tuple containing the width and height of the image
|
||||
fn dimensions(&self) -> (u64, u64);
|
||||
@ -435,7 +434,7 @@ pub trait ImageDecoder: Sized {
|
||||
}
|
||||
|
||||
/// ImageDecoderExt trait
|
||||
pub trait ImageDecoderExt: ImageDecoder + Sized {
|
||||
pub trait ImageDecoderExt<'a>: ImageDecoder<'a> + Sized {
|
||||
/// Read a rectangular section of the image.
|
||||
fn read_rect(
|
||||
&mut self,
|
||||
@ -497,48 +496,6 @@ impl<'a, I: GenericImageView> Iterator for Pixels<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable pixel iterator
|
||||
///
|
||||
/// DEPRECATED: It is currently not possible to create a safe iterator for this in Rust. You have to use an iterator over the image buffer instead.
|
||||
pub struct MutPixels<'a, I: ?Sized + 'a> {
|
||||
image: &'a mut I,
|
||||
x: u32,
|
||||
y: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl<'a, I: GenericImage + 'a> Iterator for MutPixels<'a, I>
|
||||
where
|
||||
I::Pixel: 'a,
|
||||
<I::Pixel as Pixel>::Subpixel: 'a,
|
||||
{
|
||||
type Item = (u32, u32, &'a mut I::Pixel);
|
||||
|
||||
fn next(&mut self) -> Option<(u32, u32, &'a mut I::Pixel)> {
|
||||
if self.x >= self.width {
|
||||
self.x = 0;
|
||||
self.y += 1;
|
||||
}
|
||||
|
||||
if self.y >= self.height {
|
||||
None
|
||||
} else {
|
||||
let tmp = self.image.get_pixel_mut(self.x, self.y);
|
||||
|
||||
// NOTE: This is potentially dangerous. It would require the signature fn next(&'a mut self) to be safe.
|
||||
// error: lifetime of `self` is too short to guarantee its contents can be safely reborrowed...
|
||||
let ptr = unsafe { mem::transmute(tmp) };
|
||||
|
||||
let p = (self.x, self.y, ptr);
|
||||
|
||||
self.x += 1;
|
||||
|
||||
Some(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to inspect an image.
|
||||
pub trait GenericImageView {
|
||||
/// The type of pixel.
|
||||
@ -585,6 +542,7 @@ pub trait GenericImageView {
|
||||
/// Returns the pixel located at (x, y)
|
||||
///
|
||||
/// This function can be implemented in a way that ignores bounds checking.
|
||||
#[deprecated = "Generally offers little advantage over get_pixel. If you must, prefer dedicated methods or other realizations on the specific image type instead."]
|
||||
unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
|
||||
self.get_pixel(x, y)
|
||||
}
|
||||
@ -637,6 +595,7 @@ pub trait GenericImage: GenericImageView {
|
||||
/// Puts a pixel at location (x, y)
|
||||
///
|
||||
/// This function can be implemented in a way that ignores bounds checking.
|
||||
#[deprecated = "Generally offers little advantage over put_pixel. If you must, prefer dedicated methods or other realizations on the specific image type instead."]
|
||||
unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
|
||||
self.put_pixel(x, y, pixel);
|
||||
}
|
||||
@ -646,24 +605,6 @@ pub trait GenericImage: GenericImageView {
|
||||
/// DEPRECATED: This method will be removed. Blend the pixel directly instead.
|
||||
fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
|
||||
|
||||
/// Returns an Iterator over mutable pixels of this image.
|
||||
/// The iterator yields the coordinates of each pixel
|
||||
/// along with a mutable reference to them.
|
||||
#[deprecated(
|
||||
note = "This cannot be implemented safely in Rust. Please use the image buffer directly."
|
||||
)]
|
||||
fn pixels_mut(&mut self) -> MutPixels<Self> {
|
||||
let (width, height) = self.dimensions();
|
||||
|
||||
MutPixels {
|
||||
image: self,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies all of the pixels from another image into this image.
|
||||
///
|
||||
/// The other image is copied with the top-left corner of the
|
||||
@ -686,10 +627,8 @@ pub trait GenericImage: GenericImageView {
|
||||
|
||||
for i in 0..other.width() {
|
||||
for k in 0..other.height() {
|
||||
unsafe {
|
||||
let p = other.unsafe_get_pixel(i, k);
|
||||
self.unsafe_put_pixel(i + x, k + y, p);
|
||||
}
|
||||
let p = other.get_pixel(i, k);
|
||||
self.put_pixel(i + x, k + y, p);
|
||||
}
|
||||
}
|
||||
true
|
||||
@ -839,8 +778,9 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io;
|
||||
|
||||
use super::{GenericImage, GenericImageView};
|
||||
use super::{ColorType, ImageDecoder, ImageResult, GenericImage, GenericImageView, load_rect};
|
||||
use buffer::ImageBuffer;
|
||||
use color::Rgba;
|
||||
|
||||
@ -913,11 +853,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_load_rect() {
|
||||
use super::*;
|
||||
|
||||
struct MockDecoder {scanline_number: u64, scanline_bytes: u64}
|
||||
impl ImageDecoder for MockDecoder {
|
||||
type Reader = Box<::std::io::Read>;
|
||||
impl<'a> ImageDecoder<'a> for MockDecoder {
|
||||
type Reader = Box<dyn io::Read>;
|
||||
fn dimensions(&self) -> (u64, u64) {(5, 5)}
|
||||
fn colortype(&self) -> ColorType { ColorType::Gray(8) }
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {unimplemented!()}
|
||||
|
35
third_party/rust/image/src/imageops/affine.rs
vendored
35
third_party/rust/image/src/imageops/affine.rs
vendored
@ -4,13 +4,10 @@ use buffer::{ImageBuffer, Pixel};
|
||||
use image::GenericImageView;
|
||||
|
||||
/// Rotate an image 90 degrees clockwise.
|
||||
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
|
||||
pub fn rotate90<I: GenericImageView + 'static>(
|
||||
pub fn rotate90<I: GenericImageView>(
|
||||
image: &I,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
where I::Pixel: 'static,
|
||||
{
|
||||
let (width, height) = image.dimensions();
|
||||
let mut out = ImageBuffer::new(height, width);
|
||||
@ -26,13 +23,10 @@ where
|
||||
}
|
||||
|
||||
/// Rotate an image 180 degrees clockwise.
|
||||
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
|
||||
pub fn rotate180<I: GenericImageView + 'static>(
|
||||
pub fn rotate180<I: GenericImageView>(
|
||||
image: &I,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
where I::Pixel: 'static,
|
||||
{
|
||||
let (width, height) = image.dimensions();
|
||||
let mut out = ImageBuffer::new(width, height);
|
||||
@ -48,13 +42,10 @@ where
|
||||
}
|
||||
|
||||
/// Rotate an image 270 degrees clockwise.
|
||||
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
|
||||
pub fn rotate270<I: GenericImageView + 'static>(
|
||||
pub fn rotate270<I: GenericImageView>(
|
||||
image: &I,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
where I::Pixel: 'static,
|
||||
{
|
||||
let (width, height) = image.dimensions();
|
||||
let mut out = ImageBuffer::new(height, width);
|
||||
@ -70,13 +61,10 @@ where
|
||||
}
|
||||
|
||||
/// Flip an image horizontally
|
||||
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
|
||||
pub fn flip_horizontal<I: GenericImageView + 'static>(
|
||||
pub fn flip_horizontal<I: GenericImageView>(
|
||||
image: &I,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
where I::Pixel: 'static,
|
||||
{
|
||||
let (width, height) = image.dimensions();
|
||||
let mut out = ImageBuffer::new(width, height);
|
||||
@ -92,13 +80,10 @@ where
|
||||
}
|
||||
|
||||
/// Flip an image vertically
|
||||
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
|
||||
pub fn flip_vertical<I: GenericImageView + 'static>(
|
||||
pub fn flip_vertical<I: GenericImageView>(
|
||||
image: &I,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
where I::Pixel: 'static,
|
||||
{
|
||||
let (width, height) = image.dimensions();
|
||||
let mut out = ImageBuffer::new(width, height);
|
||||
|
@ -196,7 +196,7 @@ impl ColorMap for BiLevel {
|
||||
|
||||
#[inline(always)]
|
||||
fn index_of(&self, color: &Luma<u8>) -> usize {
|
||||
let luma = color.data;
|
||||
let luma = color.0;
|
||||
if luma[0] > 127 {
|
||||
1
|
||||
} else {
|
||||
@ -207,7 +207,7 @@ impl ColorMap for BiLevel {
|
||||
#[inline(always)]
|
||||
fn map_color(&self, color: &mut Luma<u8>) {
|
||||
let new_color = 0xFF * self.index_of(color) as u8;
|
||||
let luma = &mut color.data;
|
||||
let luma = &mut color.0;
|
||||
luma[0] = new_color;
|
||||
}
|
||||
}
|
||||
|
12
third_party/rust/image/src/imageops/mod.rs
vendored
12
third_party/rust/image/src/imageops/mod.rs
vendored
@ -117,7 +117,11 @@ pub fn overlay_bounds(
|
||||
}
|
||||
|
||||
/// Overlay an image at a given coordinate (x, y)
|
||||
pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y: u32) {
|
||||
pub fn overlay<I, J>(bottom: &mut I, top: &J, x: u32, y: u32)
|
||||
where
|
||||
I: GenericImage,
|
||||
J: GenericImageView<Pixel = I::Pixel>,
|
||||
{
|
||||
let bottom_dims = bottom.dimensions();
|
||||
let top_dims = top.dimensions();
|
||||
|
||||
@ -136,7 +140,11 @@ pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y: u32) {
|
||||
}
|
||||
|
||||
/// Replace the contents of an image at a given coordinate (x, y)
|
||||
pub fn replace<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y: u32) {
|
||||
pub fn replace<I, J>(bottom: &mut I, top: &J, x: u32, y: u32)
|
||||
where
|
||||
I: GenericImage,
|
||||
J: GenericImageView<Pixel = I::Pixel>,
|
||||
{
|
||||
let bottom_dims = bottom.dimensions();
|
||||
let top_dims = top.dimensions();
|
||||
|
||||
|
23
third_party/rust/image/src/imageops/sample.rs
vendored
23
third_party/rust/image/src/imageops/sample.rs
vendored
@ -13,7 +13,7 @@ use math::utils::clamp;
|
||||
use traits::{Enlargeable, Primitive};
|
||||
|
||||
/// Available Sampling Filters
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum FilterType {
|
||||
/// Nearest Neighbor
|
||||
Nearest,
|
||||
@ -34,7 +34,7 @@ pub enum FilterType {
|
||||
/// A Representation of a separable filter.
|
||||
pub struct Filter<'a> {
|
||||
/// The filter's filter function.
|
||||
pub kernel: Box<Fn(f32) -> f32 + 'a>,
|
||||
pub kernel: Box<dyn Fn(f32) -> f32 + 'a>,
|
||||
|
||||
/// The window on which this filter operates.
|
||||
pub support: f32,
|
||||
@ -122,14 +122,13 @@ pub fn box_kernel(_x: f32) -> f32 {
|
||||
// The height of the image remains unchanged.
|
||||
// ```new_width``` is the desired width of the new image
|
||||
// ```filter``` is the filter to use for sampling.
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
fn horizontal_sample<I, P, S>(
|
||||
image: &I,
|
||||
new_width: u32,
|
||||
filter: &mut Filter,
|
||||
) -> ImageBuffer<P, Vec<S>>
|
||||
where
|
||||
I: GenericImageView<Pixel = P> + 'static,
|
||||
I: GenericImageView<Pixel = P>,
|
||||
P: Pixel<Subpixel = S> + 'static,
|
||||
S: Primitive + 'static,
|
||||
{
|
||||
@ -214,14 +213,13 @@ where
|
||||
// The width of the image remains unchanged.
|
||||
// ```new_height``` is the desired height of the new image
|
||||
// ```filter``` is the filter to use for sampling.
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
fn vertical_sample<I, P, S>(
|
||||
image: &I,
|
||||
new_height: u32,
|
||||
filter: &mut Filter,
|
||||
) -> ImageBuffer<P, Vec<S>>
|
||||
where
|
||||
I: GenericImageView<Pixel = P> + 'static,
|
||||
I: GenericImageView<Pixel = P>,
|
||||
P: Pixel<Subpixel = S> + 'static,
|
||||
S: Primitive + 'static,
|
||||
{
|
||||
@ -566,10 +564,9 @@ where
|
||||
|
||||
/// Perform a 3x3 box filter on the supplied image.
|
||||
/// ```kernel``` is an array of the filter weights of length 9.
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
pub fn filter3x3<I, P, S>(image: &I, kernel: &[f32]) -> ImageBuffer<P, Vec<S>>
|
||||
where
|
||||
I: GenericImageView<Pixel = P> + 'static,
|
||||
I: GenericImageView<Pixel = P>,
|
||||
P: Pixel<Subpixel = S> + 'static,
|
||||
S: Primitive + 'static,
|
||||
{
|
||||
@ -647,8 +644,7 @@ where
|
||||
/// Resize the supplied image to the specified dimensions.
|
||||
/// ```nwidth``` and ```nheight``` are the new dimensions.
|
||||
/// ```filter``` is the sampling filter to use.
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
pub fn resize<I: GenericImageView + 'static>(
|
||||
pub fn resize<I: GenericImageView>(
|
||||
image: &I,
|
||||
nwidth: u32,
|
||||
nheight: u32,
|
||||
@ -687,14 +683,12 @@ where
|
||||
|
||||
/// Performs a Gaussian blur on the supplied image.
|
||||
/// ```sigma``` is a measure of how much to blur by.
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
pub fn blur<I: GenericImageView + 'static>(
|
||||
pub fn blur<I: GenericImageView>(
|
||||
image: &I,
|
||||
sigma: f32,
|
||||
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
|
||||
where
|
||||
I::Pixel: 'static,
|
||||
<I::Pixel as Pixel>::Subpixel: 'static,
|
||||
{
|
||||
let sigma = if sigma < 0.0 { 1.0 } else { sigma };
|
||||
|
||||
@ -716,10 +710,9 @@ where
|
||||
/// ```threshold``` is the threshold for the difference between
|
||||
///
|
||||
/// See <https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking>
|
||||
// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
|
||||
pub fn unsharpen<I, P, S>(image: &I, sigma: f32, threshold: i32) -> ImageBuffer<P, Vec<S>>
|
||||
where
|
||||
I: GenericImageView<Pixel = P> + 'static,
|
||||
I: GenericImageView<Pixel = P>,
|
||||
P: Pixel<Subpixel = S> + 'static,
|
||||
S: Primitive + 'static,
|
||||
{
|
||||
|
26
third_party/rust/image/src/jpeg/decoder.rs
vendored
26
third_party/rust/image/src/jpeg/decoder.rs
vendored
@ -1,6 +1,8 @@
|
||||
extern crate jpeg_decoder;
|
||||
|
||||
use std::io::{Cursor, Read};
|
||||
use std::io::{self, Cursor, Read};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use color::ColorType;
|
||||
use image::{ImageDecoder, ImageError, ImageResult};
|
||||
@ -31,8 +33,24 @@ impl<R: Read> JPEGDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> ImageDecoder for JPEGDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct JpegReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for JpegReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for JPEGDecoder<R> {
|
||||
type Reader = JpegReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.metadata.width as u64, self.metadata.height as u64)
|
||||
@ -43,7 +61,7 @@ impl<R: Read> ImageDecoder for JPEGDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(JpegReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
|
62
third_party/rust/image/src/jpeg/encoder.rs
vendored
62
third_party/rust/image/src/jpeg/encoder.rs
vendored
@ -182,10 +182,10 @@ impl<'a, W: Write + 'a> BitWriter<'a, W> {
|
||||
|
||||
while self.nbits >= 8 {
|
||||
let byte = (self.accumulator & (0xFFFF_FFFFu32 << 24)) >> 24;
|
||||
try!(self.w.write_all(&[byte as u8]));
|
||||
self.w.write_all(&[byte as u8])?;
|
||||
|
||||
if byte == 0xFF {
|
||||
try!(self.w.write_all(&[0x00]));
|
||||
self.w.write_all(&[0x00])?;
|
||||
}
|
||||
|
||||
self.nbits -= 8;
|
||||
@ -221,8 +221,8 @@ impl<'a, W: Write + 'a> BitWriter<'a, W> {
|
||||
let diff = dcval - prevdc;
|
||||
let (size, value) = encode_coefficient(diff);
|
||||
|
||||
try!(self.huffman_encode(size, dctable));
|
||||
try!(self.write_bits(value, size));
|
||||
self.huffman_encode(size, dctable)?;
|
||||
self.write_bits(value, size)?;
|
||||
|
||||
// Figure F.2
|
||||
let mut zero_run = 0;
|
||||
@ -233,22 +233,22 @@ impl<'a, W: Write + 'a> BitWriter<'a, W> {
|
||||
|
||||
if block[UNZIGZAG[k] as usize] == 0 {
|
||||
if k == 63 {
|
||||
try!(self.huffman_encode(0x00, actable));
|
||||
self.huffman_encode(0x00, actable)?;
|
||||
break;
|
||||
}
|
||||
|
||||
zero_run += 1;
|
||||
} else {
|
||||
while zero_run > 15 {
|
||||
try!(self.huffman_encode(0xF0, actable));
|
||||
self.huffman_encode(0xF0, actable)?;
|
||||
zero_run -= 16;
|
||||
}
|
||||
|
||||
let (size, value) = encode_coefficient(block[UNZIGZAG[k] as usize]);
|
||||
let symbol = (zero_run << 4) | size;
|
||||
|
||||
try!(self.huffman_encode(symbol, actable));
|
||||
try!(self.write_bits(value, size));
|
||||
self.huffman_encode(symbol, actable)?;
|
||||
self.write_bits(value, size)?;
|
||||
|
||||
zero_run = 0;
|
||||
|
||||
@ -262,12 +262,12 @@ impl<'a, W: Write + 'a> BitWriter<'a, W> {
|
||||
}
|
||||
|
||||
fn write_segment(&mut self, marker: u8, data: Option<&[u8]>) -> io::Result<()> {
|
||||
try!(self.w.write_all(&[0xFF]));
|
||||
try!(self.w.write_all(&[marker]));
|
||||
self.w.write_all(&[0xFF])?;
|
||||
self.w.write_all(&[marker])?;
|
||||
|
||||
if let Some(b) = data {
|
||||
try!(self.w.write_u16::<BigEndian>(b.len() as u16 + 2));
|
||||
try!(self.w.write_all(b));
|
||||
self.w.write_u16::<BigEndian>(b.len() as u16 + 2)?;
|
||||
self.w.write_all(b)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -377,12 +377,12 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
let n = color::num_components(c);
|
||||
let num_components = if n == 1 || n == 2 { 1 } else { 3 };
|
||||
|
||||
try!(self.writer.write_segment(SOI, None));
|
||||
self.writer.write_segment(SOI, None)?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
build_jfif_header(&mut buf);
|
||||
try!(self.writer.write_segment(APP0, Some(&buf)));
|
||||
self.writer.write_segment(APP0, Some(&buf))?;
|
||||
|
||||
build_frame_header(
|
||||
&mut buf,
|
||||
@ -391,14 +391,14 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
height as u16,
|
||||
&self.components[..num_components],
|
||||
);
|
||||
try!(self.writer.write_segment(SOF0, Some(&buf)));
|
||||
self.writer.write_segment(SOF0, Some(&buf))?;
|
||||
|
||||
assert_eq!(self.tables.len() / 64, 2);
|
||||
let numtables = if num_components == 1 { 1 } else { 2 };
|
||||
|
||||
for (i, table) in self.tables.chunks(64).enumerate().take(numtables) {
|
||||
build_quantization_segment(&mut buf, 8, i as u8, table);
|
||||
try!(self.writer.write_segment(DQT, Some(&buf)));
|
||||
self.writer.write_segment(DQT, Some(&buf))?;
|
||||
}
|
||||
|
||||
build_huffman_segment(
|
||||
@ -408,7 +408,7 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
&STD_LUMA_DC_CODE_LENGTHS,
|
||||
&STD_LUMA_DC_VALUES,
|
||||
);
|
||||
try!(self.writer.write_segment(DHT, Some(&buf)));
|
||||
self.writer.write_segment(DHT, Some(&buf))?;
|
||||
|
||||
build_huffman_segment(
|
||||
&mut buf,
|
||||
@ -417,7 +417,7 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
&STD_LUMA_AC_CODE_LENGTHS,
|
||||
&STD_LUMA_AC_VALUES,
|
||||
);
|
||||
try!(self.writer.write_segment(DHT, Some(&buf)));
|
||||
self.writer.write_segment(DHT, Some(&buf))?;
|
||||
|
||||
if num_components == 3 {
|
||||
build_huffman_segment(
|
||||
@ -427,7 +427,7 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
&STD_CHROMA_DC_CODE_LENGTHS,
|
||||
&STD_CHROMA_DC_VALUES,
|
||||
);
|
||||
try!(self.writer.write_segment(DHT, Some(&buf)));
|
||||
self.writer.write_segment(DHT, Some(&buf))?;
|
||||
|
||||
build_huffman_segment(
|
||||
&mut buf,
|
||||
@ -436,24 +436,24 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
&STD_CHROMA_AC_CODE_LENGTHS,
|
||||
&STD_CHROMA_AC_VALUES,
|
||||
);
|
||||
try!(self.writer.write_segment(DHT, Some(&buf)));
|
||||
self.writer.write_segment(DHT, Some(&buf))?;
|
||||
}
|
||||
|
||||
build_scan_header(&mut buf, &self.components[..num_components]);
|
||||
try!(self.writer.write_segment(SOS, Some(&buf)));
|
||||
self.writer.write_segment(SOS, Some(&buf))?;
|
||||
|
||||
match c {
|
||||
color::ColorType::RGB(8) => {
|
||||
try!(self.encode_rgb(image, width as usize, height as usize, 3))
|
||||
self.encode_rgb(image, width as usize, height as usize, 3)?
|
||||
}
|
||||
color::ColorType::RGBA(8) => {
|
||||
try!(self.encode_rgb(image, width as usize, height as usize, 4))
|
||||
self.encode_rgb(image, width as usize, height as usize, 4)?
|
||||
}
|
||||
color::ColorType::Gray(8) => {
|
||||
try!(self.encode_gray(image, width as usize, height as usize, 1))
|
||||
self.encode_gray(image, width as usize, height as usize, 1)?
|
||||
}
|
||||
color::ColorType::GrayA(8) => {
|
||||
try!(self.encode_gray(image, width as usize, height as usize, 2))
|
||||
self.encode_gray(image, width as usize, height as usize, 2)?
|
||||
}
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
@ -466,8 +466,8 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
}
|
||||
};
|
||||
|
||||
try!(self.writer.pad_byte());
|
||||
try!(self.writer.write_segment(EOI, None));
|
||||
self.writer.pad_byte()?;
|
||||
self.writer.write_segment(EOI, None)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -499,7 +499,7 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
let la = &*self.luma_actable;
|
||||
let ld = &*self.luma_dctable;
|
||||
|
||||
y_dcprev = try!(self.writer.write_block(&dct_yblock, y_dcprev, ld, la));
|
||||
y_dcprev = self.writer.write_block(&dct_yblock, y_dcprev, ld, la)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,9 +562,9 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
|
||||
let cd = &*self.chroma_dctable;
|
||||
let ca = &*self.chroma_actable;
|
||||
|
||||
y_dcprev = try!(self.writer.write_block(&dct_yblock, y_dcprev, ld, la));
|
||||
cb_dcprev = try!(self.writer.write_block(&dct_cb_block, cb_dcprev, cd, ca));
|
||||
cr_dcprev = try!(self.writer.write_block(&dct_cr_block, cr_dcprev, cd, ca));
|
||||
y_dcprev = self.writer.write_block(&dct_yblock, y_dcprev, ld, la)?;
|
||||
cb_dcprev = self.writer.write_block(&dct_cb_block, cb_dcprev, cd, ca)?;
|
||||
cr_dcprev = self.writer.write_block(&dct_cr_block, cr_dcprev, cd, ca)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
23
third_party/rust/image/src/lib.rs
vendored
23
third_party/rust/image/src/lib.rs
vendored
@ -14,6 +14,8 @@ extern crate lzw;
|
||||
extern crate num_iter;
|
||||
extern crate num_rational;
|
||||
extern crate num_traits;
|
||||
#[cfg(feature = "hdr")]
|
||||
extern crate scoped_threadpool;
|
||||
#[cfg(all(test, feature = "benchmarks"))]
|
||||
extern crate test;
|
||||
|
||||
@ -34,7 +36,6 @@ pub use image::{AnimationDecoder,
|
||||
ImageDecoderExt,
|
||||
ImageError,
|
||||
ImageResult,
|
||||
MutPixels,
|
||||
// Iterators
|
||||
Pixels,
|
||||
SubImage};
|
||||
@ -61,7 +62,7 @@ pub use traits::Primitive;
|
||||
|
||||
// Opening and loading images
|
||||
pub use dynimage::{guess_format, load, load_from_memory, load_from_memory_with_format, open,
|
||||
save_buffer};
|
||||
save_buffer, save_buffer_with_format, image_dimensions};
|
||||
|
||||
pub use dynimage::DynamicImage::{self, ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8, ImageBgr8, ImageBgra8};
|
||||
|
||||
@ -108,6 +109,24 @@ mod image;
|
||||
mod traits;
|
||||
mod utils;
|
||||
|
||||
// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
|
||||
// the macro invocation.
|
||||
//
|
||||
// The inspiration for the macro and implementation is from
|
||||
// <https://github.com/GuillaumeGomez/doc-comment>
|
||||
//
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2018 Guillaume Gomez
|
||||
macro_rules! insert_as_doc {
|
||||
{ $content:expr } => {
|
||||
#[doc = $content] extern { }
|
||||
}
|
||||
}
|
||||
|
||||
// Provides the README.md as doc, to ensure the example works!
|
||||
insert_as_doc!(include_str!("../README.md"));
|
||||
|
||||
// Copies data from `src` to `dst`
|
||||
//
|
||||
// Panics if the length of `dst` is less than the length of `src`.
|
||||
|
4
third_party/rust/image/src/math/nq.rs
vendored
4
third_party/rust/image/src/math/nq.rs
vendored
@ -2,7 +2,7 @@
|
||||
//! See "Kohonen neural networks for optimal colour quantization"
|
||||
//! in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
|
||||
//! for a discussion of the algorithm.
|
||||
//! See also <http://www.acm.org/~dekker/NEUQUANT.HTML>
|
||||
//! See also <https://scientificgems.wordpress.com/stuff/neuquant-fast-high-quality-image-quantization/>
|
||||
|
||||
/* NeuQuant Neural-Net Quantization Algorithm
|
||||
* ------------------------------------------
|
||||
@ -13,7 +13,7 @@
|
||||
* See "Kohonen neural networks for optimal colour quantization"
|
||||
* in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
|
||||
* for a discussion of the algorithm.
|
||||
* See also http://www.acm.org/~dekker/NEUQUANT.HTML
|
||||
* See also https://scientificgems.wordpress.com/stuff/neuquant-fast-high-quality-image-quantization/
|
||||
*
|
||||
* Any party obtaining a copy of these files from the author, directly or
|
||||
* indirectly, is granted, free of charge, a full and unrestricted irrevocable,
|
||||
|
102
third_party/rust/image/src/png.rs
vendored
102
third_party/rust/image/src/png.rs
vendored
@ -8,13 +8,86 @@
|
||||
|
||||
extern crate png;
|
||||
|
||||
use self::png::HasParameters;
|
||||
|
||||
use std::io::{self, Cursor, Read, Write};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use color::ColorType;
|
||||
use image::{ImageDecoder, ImageError, ImageResult};
|
||||
|
||||
/// PNG Reader
|
||||
///
|
||||
/// This reader will try to read the png one row at a time,
|
||||
/// however for interlaced png files this is not posible and
|
||||
/// these are therefore readed at once.
|
||||
pub struct PNGReader<R: Read> {
|
||||
reader: png::Reader<R>,
|
||||
buffer: Vec<u8>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<R: Read> PNGReader<R> {
|
||||
fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
|
||||
let len = reader.output_buffer_size();
|
||||
// Since interlaced images do not come in
|
||||
// scanline order it is almost impossible to
|
||||
// read them in a streaming fashion, however
|
||||
// this shouldn't be a too big of a problem
|
||||
// as most interlaced images should fit in memory.
|
||||
let buffer = if reader.info().interlaced {
|
||||
let mut buffer = vec![0; len];
|
||||
reader.next_frame(&mut buffer)?;
|
||||
buffer
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(PNGReader {
|
||||
reader,
|
||||
buffer,
|
||||
index: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Read for PNGReader<R> {
|
||||
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
|
||||
// io::Write::write for slice cannot fail
|
||||
let readed = buf.write(&self.buffer[self.index..]).unwrap();
|
||||
|
||||
let mut bytes = readed;
|
||||
self.index += readed;
|
||||
|
||||
while self.index + 1 >= self.buffer.len() {
|
||||
match self.reader.next_row()? {
|
||||
Some(row) => {
|
||||
// Faster to copy directly to external buffer
|
||||
let readed = buf.write(row).unwrap();
|
||||
bytes += readed;
|
||||
|
||||
self.buffer = (&row[readed..]).to_owned();
|
||||
self.index = 0;
|
||||
}
|
||||
None => return Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
let mut bytes = self.buffer.len();
|
||||
buf.extend_from_slice(&self.buffer);
|
||||
self.buffer = Vec::new();
|
||||
self.index = 0;
|
||||
|
||||
while let Some(row) = self.reader.next_row()? {
|
||||
buf.extend_from_slice(row);
|
||||
bytes += row.len();
|
||||
}
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// PNG decoder
|
||||
pub struct PNGDecoder<R: Read> {
|
||||
colortype: ColorType,
|
||||
@ -24,7 +97,10 @@ pub struct PNGDecoder<R: Read> {
|
||||
impl<R: Read> PNGDecoder<R> {
|
||||
/// Creates a new decoder that decodes from the stream ```r```
|
||||
pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
|
||||
let decoder = png::Decoder::new(r);
|
||||
let limits = png::Limits {
|
||||
bytes: usize::max_value(),
|
||||
};
|
||||
let decoder = png::Decoder::new_with_limits(r, limits);
|
||||
let (_, mut reader) = decoder.read_info()?;
|
||||
let colortype = reader.output_color_type().into();
|
||||
|
||||
@ -32,8 +108,8 @@ impl<R: Read> PNGDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> ImageDecoder for PNGDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for PNGDecoder<R> {
|
||||
type Reader = PNGReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
let (w, h) = self.reader.info().size();
|
||||
@ -45,14 +121,20 @@ impl<R: Read> ImageDecoder for PNGDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
PNGReader::new(self.reader)
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
// This should be slightly faster than the default implementation
|
||||
let mut data = vec![0; self.reader.output_buffer_size()];
|
||||
self.reader.next_frame(&mut data)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn scanline_bytes(&self) -> u64 {
|
||||
let width = self.reader.info().width;
|
||||
self.reader.output_line_size(width) as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// PNG encoder
|
||||
@ -72,8 +154,9 @@ impl<W: Write> PNGEncoder<W> {
|
||||
pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
|
||||
let (ct, bits) = color.into();
|
||||
let mut encoder = png::Encoder::new(self.w, width, height);
|
||||
encoder.set(ct).set(bits);
|
||||
let mut writer = try!(encoder.write_header());
|
||||
encoder.set_color(ct);
|
||||
encoder.set_depth(bits);
|
||||
let mut writer = encoder.write_header()?;
|
||||
writer.write_image_data(data).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
@ -120,6 +203,7 @@ impl From<png::DecodingError> for ImageError {
|
||||
CorruptFlateStream => {
|
||||
ImageError::FormatError("compressed data stream corrupted".into())
|
||||
}
|
||||
LimitsExceeded => ImageError::InsufficientMemory,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
third_party/rust/image/src/pnm/decoder.rs
vendored
36
third_party/rust/image/src/pnm/decoder.rs
vendored
@ -1,6 +1,8 @@
|
||||
use std::io::{self, BufRead, BufReader, Cursor, Read};
|
||||
use std::str::{self, FromStr};
|
||||
use std::fmt::Display;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};
|
||||
use super::{HeaderRecord, PNMHeader, PNMSubtype, SampleEncoding};
|
||||
@ -27,7 +29,7 @@ trait Sample {
|
||||
fn from_bytes(bytes: &[u8], width: u32, height: u32, samples: u32)
|
||||
-> ImageResult<Vec<u8>>;
|
||||
|
||||
fn from_ascii(reader: &mut Read, width: u32, height: u32, samples: u32)
|
||||
fn from_ascii(reader: &mut dyn Read, width: u32, height: u32, samples: u32)
|
||||
-> ImageResult<Vec<u8>>;
|
||||
}
|
||||
|
||||
@ -406,8 +408,24 @@ trait HeaderReader: BufRead {
|
||||
|
||||
impl<R: Read> HeaderReader for BufReader<R> {}
|
||||
|
||||
impl<R: Read> ImageDecoder for PNMDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct PnmReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for PnmReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for PNMDecoder<R> {
|
||||
type Reader = PnmReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.header.width() as u64, self.header.height() as u64)
|
||||
@ -418,7 +436,7 @@ impl<R: Read> ImageDecoder for PNMDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(PnmReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
@ -482,7 +500,7 @@ impl TupleType {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_separated_ascii<T: FromStr>(reader: &mut Read) -> ImageResult<T>
|
||||
fn read_separated_ascii<T: FromStr>(reader: &mut dyn Read) -> ImageResult<T>
|
||||
where T::Err: Display
|
||||
{
|
||||
let is_separator = |v: &u8| match *v {
|
||||
@ -529,7 +547,7 @@ impl Sample for U8 {
|
||||
}
|
||||
|
||||
fn from_ascii(
|
||||
reader: &mut Read,
|
||||
reader: &mut dyn Read,
|
||||
width: u32,
|
||||
height: u32,
|
||||
samples: u32,
|
||||
@ -562,7 +580,7 @@ impl Sample for U16 {
|
||||
}
|
||||
|
||||
fn from_ascii(
|
||||
reader: &mut Read,
|
||||
reader: &mut dyn Read,
|
||||
width: u32,
|
||||
height: u32,
|
||||
samples: u32,
|
||||
@ -596,7 +614,7 @@ impl Sample for PbmBit {
|
||||
}
|
||||
|
||||
fn from_ascii(
|
||||
reader: &mut Read,
|
||||
reader: &mut dyn Read,
|
||||
width: u32,
|
||||
height: u32,
|
||||
samples: u32,
|
||||
@ -650,7 +668,7 @@ impl Sample for BWBit {
|
||||
}
|
||||
|
||||
fn from_ascii(
|
||||
_reader: &mut Read,
|
||||
_reader: &mut dyn Read,
|
||||
_width: u32,
|
||||
_height: u32,
|
||||
_samples: u32,
|
||||
|
16
third_party/rust/image/src/pnm/encoder.rs
vendored
16
third_party/rust/image/src/pnm/encoder.rs
vendored
@ -170,10 +170,10 @@ impl<W: Write> PNMEncoder<W> {
|
||||
let (maxval, tupltype) = match color {
|
||||
ColorType::Gray(1) => (1, ArbitraryTuplType::BlackAndWhite),
|
||||
ColorType::GrayA(1) => (1, ArbitraryTuplType::BlackAndWhiteAlpha),
|
||||
ColorType::Gray(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::Grayscale),
|
||||
ColorType::GrayA(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::GrayscaleAlpha),
|
||||
ColorType::RGB(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::RGB),
|
||||
ColorType::RGBA(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::RGBAlpha),
|
||||
ColorType::Gray(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::Grayscale),
|
||||
ColorType::GrayA(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::GrayscaleAlpha),
|
||||
ColorType::RGB(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::RGB),
|
||||
ColorType::RGBA(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::RGBAlpha),
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -251,7 +251,7 @@ impl<W: Write> PNMEncoder<W> {
|
||||
///
|
||||
/// Returns how the body should be written if successful.
|
||||
fn write_with_header(
|
||||
writer: &mut Write,
|
||||
writer: &mut dyn Write,
|
||||
header: &PNMHeader,
|
||||
image: FlatSamples,
|
||||
width: u32,
|
||||
@ -472,7 +472,7 @@ impl<'a> CheckedHeaderColor<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CheckedHeader<'a> {
|
||||
fn write_header(self, writer: &mut Write) -> io::Result<TupleEncoding<'a>> {
|
||||
fn write_header(self, writer: &mut dyn Write) -> io::Result<TupleEncoding<'a>> {
|
||||
self.header().write(writer)?;
|
||||
Ok(self.encoding)
|
||||
}
|
||||
@ -482,7 +482,7 @@ impl<'a> CheckedHeader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
struct SampleWriter<'a>(&'a mut Write);
|
||||
struct SampleWriter<'a>(&'a mut dyn Write);
|
||||
|
||||
impl<'a> SampleWriter<'a> {
|
||||
fn write_samples_ascii<V>(self, samples: V) -> io::Result<()>
|
||||
@ -596,7 +596,7 @@ impl<'a> From<&'a [u16]> for FlatSamples<'a> {
|
||||
}
|
||||
|
||||
impl<'a> TupleEncoding<'a> {
|
||||
fn write_image(&self, writer: &mut Write) -> io::Result<()> {
|
||||
fn write_image(&self, writer: &mut dyn Write) -> io::Result<()> {
|
||||
match *self {
|
||||
TupleEncoding::PbmBits {
|
||||
samples: FlatSamples::U8(samples),
|
||||
|
2
third_party/rust/image/src/pnm/header.rs
vendored
2
third_party/rust/image/src/pnm/header.rs
vendored
@ -232,7 +232,7 @@ impl PNMHeader {
|
||||
}
|
||||
|
||||
/// Write the header back into a binary stream
|
||||
pub fn write(&self, writer: &mut io::Write) -> io::Result<()> {
|
||||
pub fn write(&self, writer: &mut dyn io::Write) -> io::Result<()> {
|
||||
writer.write_all(self.subtype().magic_constant())?;
|
||||
match *self {
|
||||
PNMHeader {
|
||||
|
6
third_party/rust/image/src/pnm/mod.rs
vendored
6
third_party/rust/image/src/pnm/mod.rs
vendored
@ -34,7 +34,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let (header, loaded_color, loaded_image) = {
|
||||
let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let colortype = decoder.colortype();
|
||||
let image = decoder.read_image().expect("Failed to decode the image");
|
||||
let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
|
||||
@ -64,7 +64,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let (header, loaded_color, loaded_image) = {
|
||||
let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let colortype = decoder.colortype();
|
||||
let image = decoder.read_image().expect("Failed to decode the image");
|
||||
let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
|
||||
@ -89,7 +89,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let (header, loaded_color, loaded_image) = {
|
||||
let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
|
||||
let colortype = decoder.colortype();
|
||||
let image = decoder.read_image().expect("Failed to decode the image");
|
||||
let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
|
||||
|
46
third_party/rust/image/src/tga/decoder.rs
vendored
46
third_party/rust/image/src/tga/decoder.rs
vendored
@ -101,20 +101,20 @@ impl Header {
|
||||
}
|
||||
|
||||
/// Load the header with values from the reader
|
||||
fn from_reader(r: &mut Read) -> ImageResult<Header> {
|
||||
fn from_reader(r: &mut dyn Read) -> ImageResult<Header> {
|
||||
Ok(Header {
|
||||
id_length: try!(r.read_u8()),
|
||||
map_type: try!(r.read_u8()),
|
||||
image_type: try!(r.read_u8()),
|
||||
map_origin: try!(r.read_u16::<LittleEndian>()),
|
||||
map_length: try!(r.read_u16::<LittleEndian>()),
|
||||
map_entry_size: try!(r.read_u8()),
|
||||
x_origin: try!(r.read_u16::<LittleEndian>()),
|
||||
y_origin: try!(r.read_u16::<LittleEndian>()),
|
||||
image_width: try!(r.read_u16::<LittleEndian>()),
|
||||
image_height: try!(r.read_u16::<LittleEndian>()),
|
||||
pixel_depth: try!(r.read_u8()),
|
||||
image_desc: try!(r.read_u8()),
|
||||
id_length: r.read_u8()?,
|
||||
map_type: r.read_u8()?,
|
||||
image_type: r.read_u8()?,
|
||||
map_origin: r.read_u16::<LittleEndian>()?,
|
||||
map_length: r.read_u16::<LittleEndian>()?,
|
||||
map_entry_size: r.read_u8()?,
|
||||
x_origin: r.read_u16::<LittleEndian>()?,
|
||||
y_origin: r.read_u16::<LittleEndian>()?,
|
||||
image_width: r.read_u16::<LittleEndian>()?,
|
||||
image_height: r.read_u16::<LittleEndian>()?,
|
||||
pixel_depth: r.read_u8()?,
|
||||
image_desc: r.read_u8()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,7 @@ struct ColorMap {
|
||||
|
||||
impl ColorMap {
|
||||
pub fn from_reader(
|
||||
r: &mut Read,
|
||||
r: &mut dyn Read,
|
||||
start_offset: u16,
|
||||
num_entries: u16,
|
||||
bits_per_entry: u8,
|
||||
@ -136,7 +136,7 @@ impl ColorMap {
|
||||
let bytes_per_entry = (bits_per_entry as usize + 7) / 8;
|
||||
|
||||
let mut bytes = vec![0; bytes_per_entry * num_entries as usize];
|
||||
try!(r.read_exact(&mut bytes));
|
||||
r.read_exact(&mut bytes)?;
|
||||
|
||||
Ok(ColorMap {
|
||||
entry_size: bytes_per_entry,
|
||||
@ -197,7 +197,7 @@ impl<R: Read + Seek> TGADecoder<R> {
|
||||
}
|
||||
|
||||
fn read_header(&mut self) -> ImageResult<()> {
|
||||
self.header = try!(Header::from_reader(&mut self.r));
|
||||
self.header = Header::from_reader(&mut self.r)?;
|
||||
self.image_type = ImageType::new(self.header.image_type);
|
||||
self.width = self.header.image_width as usize;
|
||||
self.height = self.header.image_height as usize;
|
||||
@ -207,10 +207,10 @@ impl<R: Read + Seek> TGADecoder<R> {
|
||||
|
||||
fn read_metadata(&mut self) -> ImageResult<()> {
|
||||
if !self.has_loaded_metadata {
|
||||
try!(self.read_header());
|
||||
try!(self.read_image_id());
|
||||
try!(self.read_color_map());
|
||||
try!(self.read_color_information());
|
||||
self.read_header()?;
|
||||
self.read_image_id()?;
|
||||
self.read_color_map()?;
|
||||
self.read_color_information()?;
|
||||
self.has_loaded_metadata = true;
|
||||
}
|
||||
Ok(())
|
||||
@ -326,7 +326,7 @@ impl<R: Read + Seek> TGADecoder<R> {
|
||||
} else {
|
||||
let num_raw_bytes = self.width * self.height * self.bytes_per_pixel;
|
||||
let mut buf = vec![0; num_raw_bytes];
|
||||
try!(self.r.by_ref().read_exact(&mut buf));
|
||||
self.r.by_ref().read_exact(&mut buf)?;
|
||||
buf
|
||||
};
|
||||
|
||||
@ -347,7 +347,7 @@ impl<R: Read + Seek> TGADecoder<R> {
|
||||
let mut pixel_data = Vec::with_capacity(num_bytes);
|
||||
|
||||
while pixel_data.len() < num_bytes {
|
||||
let run_packet = try!(self.r.read_u8());
|
||||
let run_packet = self.r.read_u8()?;
|
||||
// If the highest bit in `run_packet` is set, then we repeat pixels
|
||||
//
|
||||
// Note: the TGA format adds 1 to both counts because having a count
|
||||
@ -498,7 +498,7 @@ impl<R: Read + Seek> TGADecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoder for TGADecoder<R> {
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TGADecoder<R> {
|
||||
type Reader = TGAReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
|
57
third_party/rust/image/src/tiff.rs
vendored
57
third_party/rust/image/src/tiff.rs
vendored
@ -8,7 +8,9 @@
|
||||
|
||||
extern crate tiff;
|
||||
|
||||
use std::io::{Cursor, Read, Seek};
|
||||
use std::io::{self, Cursor, Read, Write, Seek};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use color::ColorType;
|
||||
use image::{ImageDecoder, ImageResult, ImageError};
|
||||
@ -46,6 +48,7 @@ impl From<tiff::TiffError> for ImageError {
|
||||
tiff::TiffError::IoError(err) => ImageError::IoError(err),
|
||||
tiff::TiffError::FormatError(desc) => ImageError::FormatError(desc.to_string()),
|
||||
tiff::TiffError::UnsupportedError(desc) => ImageError::UnsupportedError(desc.to_string()),
|
||||
tiff::TiffError::LimitsExceeded => ImageError::InsufficientMemory,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,8 +66,24 @@ impl From<tiff::ColorType> for ColorType {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> ImageDecoder for TIFFDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct TiffReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for TiffReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TIFFDecoder<R> {
|
||||
type Reader = TiffReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.dimensions.0 as u64, self.dimensions.1 as u64)
|
||||
@ -75,7 +94,7 @@ impl<R: Read + Seek> ImageDecoder for TIFFDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.read_image()?))
|
||||
Ok(TiffReader(Cursor::new(self.read_image()?), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(mut self) -> ImageResult<Vec<u8>> {
|
||||
@ -85,3 +104,33 @@ impl<R: Read + Seek> ImageDecoder for TIFFDecoder<R> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Encoder for tiff images
|
||||
pub struct TiffEncoder<W> {
|
||||
w: W,
|
||||
}
|
||||
|
||||
impl<W: Write + Seek> TiffEncoder<W> {
|
||||
/// Create a new encoder that writes its output to `w`
|
||||
pub fn new(w: W) -> TiffEncoder<W> {
|
||||
TiffEncoder { w }
|
||||
}
|
||||
|
||||
/// Encodes the image `image`
|
||||
/// that has dimensions `width` and `height`
|
||||
/// and `ColorType` `c`.
|
||||
///
|
||||
/// 16-bit colortypes are not yet supported.
|
||||
pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> {
|
||||
// TODO: 16bit support
|
||||
let mut encoder = tiff::encoder::TiffEncoder::new(self.w)?;
|
||||
match color {
|
||||
ColorType::Gray(8) => encoder.write_image::<tiff::encoder::colortype::Gray8>(width, height, data)?,
|
||||
ColorType::RGB(8) => encoder.write_image::<tiff::encoder::colortype::RGB8>(width, height, data)?,
|
||||
ColorType::RGBA(8) => encoder.write_image::<tiff::encoder::colortype::RGBA8>(width, height, data)?,
|
||||
_ => return Err(ImageError::UnsupportedColor(color))
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
17
third_party/rust/image/src/utils/mod.rs
vendored
17
third_party/rust/image/src/utils/mod.rs
vendored
@ -1,7 +1,8 @@
|
||||
//! Utilities
|
||||
|
||||
use byteorder::{NativeEndian, ByteOrder};
|
||||
use num_iter::range_step;
|
||||
use std::{mem, slice};
|
||||
use std::mem;
|
||||
use std::iter::repeat;
|
||||
|
||||
#[inline(always)]
|
||||
@ -39,15 +40,7 @@ pub fn vec_u16_into_u8(vec: Vec<u16>) -> Vec<u8> {
|
||||
}
|
||||
|
||||
pub fn vec_u16_copy_u8(vec: &Vec<u16>) -> Vec<u8> {
|
||||
let original_slice = vec.as_slice();
|
||||
let ptr = original_slice.as_ptr() as *const u8;
|
||||
let len = original_slice.len() * mem::size_of::<u16>();
|
||||
|
||||
// Note: The original pointer points to `len` bytes and all bytes are initialized thus it is
|
||||
// valid for this slice and for the lifetime of the method. Also, the alignment of `u8` is
|
||||
// smaller than that of `u16` as per the assert. The `ptr` is non-null because it originates
|
||||
// from a slice itself.
|
||||
assert!(mem::align_of::<u8>() <= mem::align_of::<u16>());
|
||||
let byte_slice = unsafe { slice::from_raw_parts(ptr, len) };
|
||||
byte_slice.to_owned()
|
||||
let mut new = vec![0; vec.len() * mem::size_of::<u16>()];
|
||||
NativeEndian::write_u16_into(&vec[..], &mut new[..]);
|
||||
new
|
||||
}
|
||||
|
50
third_party/rust/image/src/webp/decoder.rs
vendored
50
third_party/rust/image/src/webp/decoder.rs
vendored
@ -1,7 +1,8 @@
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::default::Default;
|
||||
use std::io;
|
||||
use std::io::{Cursor, Read};
|
||||
use std::io::{self, Cursor, Read};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use image;
|
||||
use image::ImageDecoder;
|
||||
@ -12,7 +13,8 @@ use color;
|
||||
use super::vp8::Frame;
|
||||
use super::vp8::VP8Decoder;
|
||||
|
||||
/// A Representation of a Webp Image format decoder.
|
||||
/// Webp Image format decoder. Currently only supportes the luma channel (meaning that decoded
|
||||
/// images will be grayscale).
|
||||
pub struct WebpDecoder<R> {
|
||||
r: R,
|
||||
frame: Frame,
|
||||
@ -36,10 +38,10 @@ impl<R: Read> WebpDecoder<R> {
|
||||
|
||||
fn read_riff_header(&mut self) -> ImageResult<u32> {
|
||||
let mut riff = Vec::with_capacity(4);
|
||||
try!(self.r.by_ref().take(4).read_to_end(&mut riff));
|
||||
let size = try!(self.r.read_u32::<LittleEndian>());
|
||||
self.r.by_ref().take(4).read_to_end(&mut riff)?;
|
||||
let size = self.r.read_u32::<LittleEndian>()?;
|
||||
let mut webp = Vec::with_capacity(4);
|
||||
try!(self.r.by_ref().take(4).read_to_end(&mut webp));
|
||||
self.r.by_ref().take(4).read_to_end(&mut webp)?;
|
||||
|
||||
if &*riff != b"RIFF" {
|
||||
return Err(image::ImageError::FormatError(
|
||||
@ -58,7 +60,7 @@ impl<R: Read> WebpDecoder<R> {
|
||||
|
||||
fn read_vp8_header(&mut self) -> ImageResult<()> {
|
||||
let mut vp8 = Vec::with_capacity(4);
|
||||
try!(self.r.by_ref().take(4).read_to_end(&mut vp8));
|
||||
self.r.by_ref().take(4).read_to_end(&mut vp8)?;
|
||||
|
||||
if &*vp8 != b"VP8 " {
|
||||
return Err(image::ImageError::FormatError(
|
||||
@ -66,18 +68,18 @@ impl<R: Read> WebpDecoder<R> {
|
||||
));
|
||||
}
|
||||
|
||||
let _len = try!(self.r.read_u32::<LittleEndian>());
|
||||
let _len = self.r.read_u32::<LittleEndian>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_frame(&mut self) -> ImageResult<()> {
|
||||
let mut framedata = Vec::new();
|
||||
try!(self.r.read_to_end(&mut framedata));
|
||||
self.r.read_to_end(&mut framedata)?;
|
||||
let m = io::Cursor::new(framedata);
|
||||
|
||||
let mut v = VP8Decoder::new(m);
|
||||
let frame = try!(v.decode_frame());
|
||||
let frame = v.decode_frame()?;
|
||||
|
||||
self.frame = frame.clone();
|
||||
|
||||
@ -86,9 +88,9 @@ impl<R: Read> WebpDecoder<R> {
|
||||
|
||||
fn read_metadata(&mut self) -> ImageResult<()> {
|
||||
if !self.have_frame {
|
||||
try!(self.read_riff_header());
|
||||
try!(self.read_vp8_header());
|
||||
try!(self.read_frame());
|
||||
self.read_riff_header()?;
|
||||
self.read_vp8_header()?;
|
||||
self.read_frame()?;
|
||||
|
||||
self.have_frame = true;
|
||||
}
|
||||
@ -97,8 +99,24 @@ impl<R: Read> WebpDecoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> ImageDecoder for WebpDecoder<R> {
|
||||
type Reader = Cursor<Vec<u8>>;
|
||||
/// Wrapper struct around a `Cursor<Vec<u8>>`
|
||||
pub struct WebpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
|
||||
impl<R> Read for WebpReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
if self.0.position() == 0 && buf.is_empty() {
|
||||
mem::swap(buf, self.0.get_mut());
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read> ImageDecoder<'a> for WebpDecoder<R> {
|
||||
type Reader = WebpReader<R>;
|
||||
|
||||
fn dimensions(&self) -> (u64, u64) {
|
||||
(self.frame.width as u64, self.frame.height as u64)
|
||||
@ -109,7 +127,7 @@ impl<R: Read> ImageDecoder for WebpDecoder<R> {
|
||||
}
|
||||
|
||||
fn into_reader(self) -> ImageResult<Self::Reader> {
|
||||
Ok(Cursor::new(self.frame.ybuf))
|
||||
Ok(WebpReader(Cursor::new(self.frame.ybuf), PhantomData))
|
||||
}
|
||||
|
||||
fn read_image(self) -> ImageResult<Vec<u8>> {
|
||||
|
61
third_party/rust/image/src/webp/transform.rs
vendored
61
third_party/rust/image/src/webp/transform.rs
vendored
@ -1,41 +1,46 @@
|
||||
static CONST1: i32 = 20091;
|
||||
static CONST2: i32 = 35468;
|
||||
static CONST1: i64 = 20091;
|
||||
static CONST2: i64 = 35468;
|
||||
|
||||
pub fn idct4x4(block: &mut [i32]) {
|
||||
for i in 0usize..4 {
|
||||
let a1 = block[i] + block[8 + i];
|
||||
let b1 = block[i] - block[8 + i];
|
||||
|
||||
let t1 = (block[4 + i] * CONST2) >> 16;
|
||||
let t2 = block[12 + i] + ((block[12 + i] * CONST1) >> 16);
|
||||
let c1 = t1 - t2;
|
||||
|
||||
let t1 = block[4 + i] + ((block[4 + i] * CONST1) >> 16);
|
||||
let t2 = (block[12 + i] * CONST2) >> 16;
|
||||
let d1 = t1 + t2;
|
||||
|
||||
block[i] = a1 + d1;
|
||||
block[4 + i] = b1 + c1;
|
||||
block[4 * 3 + i] = a1 - d1;
|
||||
block[4 * 2 + i] = b1 - c1;
|
||||
// The intermediate results may overflow the types, so we stretch the type.
|
||||
fn fetch(block: &mut [i32], idx: usize) -> i64 {
|
||||
i64::from(block[idx])
|
||||
}
|
||||
|
||||
for i in 0usize..4 {
|
||||
let a1 = block[4 * i] + block[4 * i + 2];
|
||||
let b1 = block[4 * i] - block[4 * i + 2];
|
||||
let a1 = fetch(block, i) + fetch(block, 8 + i);
|
||||
let b1 = fetch(block, i) - fetch(block, 8 + i);
|
||||
|
||||
let t1 = (block[4 * i + 1] * CONST2) >> 16;
|
||||
let t2 = block[4 * i + 3] + ((block[4 * i + 3] * CONST1) >> 16);
|
||||
let t1 = (fetch(block, 4 + i) * CONST2) >> 16;
|
||||
let t2 = fetch(block, 12 + i) + ((fetch(block, 12 + i) * CONST1) >> 16);
|
||||
let c1 = t1 - t2;
|
||||
|
||||
let t1 = block[4 * i + 1] + ((block[4 * i + 1] * CONST1) >> 16);
|
||||
let t2 = (block[4 * i + 3] * CONST2) >> 16;
|
||||
let t1 = fetch(block, 4 + i) + ((fetch(block, 4 + i) * CONST1) >> 16);
|
||||
let t2 = (fetch(block, 12 + i) * CONST2) >> 16;
|
||||
let d1 = t1 + t2;
|
||||
|
||||
block[4 * i] = (a1 + d1 + 4) >> 3;
|
||||
block[4 * i + 3] = (a1 - d1 + 4) >> 3;
|
||||
block[4 * i + 1] = (b1 + c1 + 4) >> 3;
|
||||
block[4 * i + 2] = (b1 - c1 + 4) >> 3;
|
||||
block[i] = (a1 + d1) as i32;
|
||||
block[4 + i] = (b1 + c1) as i32;
|
||||
block[4 * 3 + i] = (a1 - d1) as i32;
|
||||
block[4 * 2 + i] = (b1 - c1) as i32;
|
||||
}
|
||||
|
||||
for i in 0usize..4 {
|
||||
let a1 = fetch(block, 4 * i) + fetch(block, 4 * i + 2);
|
||||
let b1 = fetch(block, 4 * i) - fetch(block, 4 * i + 2);
|
||||
|
||||
let t1 = (fetch(block, 4 * i + 1) * CONST2) >> 16;
|
||||
let t2 = fetch(block, 4 * i + 3) + ((fetch(block, 4 * i + 3) * CONST1) >> 16);
|
||||
let c1 = t1 - t2;
|
||||
|
||||
let t1 = fetch(block, 4 * i + 1) + ((fetch(block, 4 * i + 1) * CONST1) >> 16);
|
||||
let t2 = (fetch(block, 4 * i + 3) * CONST2) >> 16;
|
||||
let d1 = t1 + t2;
|
||||
|
||||
block[4 * i] = ((a1 + d1 + 4) >> 3) as i32;
|
||||
block[4 * i + 3] = ((a1 - d1 + 4) >> 3) as i32;
|
||||
block[4 * i + 1] = ((b1 + c1 + 4) >> 3) as i32;
|
||||
block[4 * i + 2] = ((b1 - c1 + 4) >> 3) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
|
450
third_party/rust/image/src/webp/vp8.rs
vendored
450
third_party/rust/image/src/webp/vp8.rs
vendored
@ -14,10 +14,11 @@
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::default::Default;
|
||||
use std::io;
|
||||
use std::cmp;
|
||||
use std::io::Read;
|
||||
|
||||
use super::transform;
|
||||
use ::{ImageError, ImageResult};
|
||||
|
||||
use math::utils::clamp;
|
||||
|
||||
@ -42,6 +43,57 @@ const B_VL_PRED: i8 = 7;
|
||||
const B_HD_PRED: i8 = 8;
|
||||
const B_HU_PRED: i8 = 9;
|
||||
|
||||
// Prediction mode enum
|
||||
#[repr(i8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum LumaMode {
|
||||
/// Predict DC using row above and column to the left.
|
||||
DC = DC_PRED,
|
||||
|
||||
/// Predict rows using row above.
|
||||
V = V_PRED,
|
||||
|
||||
/// Predict columns using column to the left.
|
||||
H = H_PRED,
|
||||
|
||||
/// Propagate second differences.
|
||||
TM = TM_PRED,
|
||||
|
||||
/// Each Y subblock is independently predicted.
|
||||
B = B_PRED,
|
||||
}
|
||||
|
||||
#[repr(i8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum ChromaMode {
|
||||
/// Predict DC using row above and column to the left.
|
||||
DC = DC_PRED,
|
||||
|
||||
/// Predict rows using row above.
|
||||
V = V_PRED,
|
||||
|
||||
/// Predict columns using column to the left.
|
||||
H = H_PRED,
|
||||
|
||||
/// Propagate second differences.
|
||||
TM = TM_PRED,
|
||||
}
|
||||
|
||||
#[repr(i8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum IntraMode {
|
||||
DC = B_DC_PRED,
|
||||
TM = B_TM_PRED,
|
||||
VE = B_VE_PRED,
|
||||
HE = B_HE_PRED,
|
||||
LD = B_LD_PRED,
|
||||
RD = B_RD_PRED,
|
||||
VR = B_VR_PRED,
|
||||
VL = B_VL_PRED,
|
||||
HD = B_HD_PRED,
|
||||
HU = B_HU_PRED,
|
||||
}
|
||||
|
||||
type Prob = u8;
|
||||
|
||||
static SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3];
|
||||
@ -630,30 +682,33 @@ impl BoolReader {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self, buf: Vec<u8>) {
|
||||
self.buf = buf;
|
||||
self.value = 0;
|
||||
|
||||
for _ in 0usize..2 {
|
||||
self.value = (self.value << 8) | u32::from(self.buf[self.index]);
|
||||
self.index += 1;
|
||||
pub fn init(&mut self, buf: Vec<u8>) -> ImageResult<()> {
|
||||
if buf.len() < 2 {
|
||||
return Err(ImageError::FormatError(
|
||||
"Expected at least 2 bytes of decoder initialization data".into()));
|
||||
}
|
||||
|
||||
self.buf = buf;
|
||||
// Direct access safe, since length has just been validated.
|
||||
self.value = (u32::from(self.buf[0]) << 8) | u32::from(self.buf[1]);
|
||||
self.index = 2;
|
||||
self.range = 255;
|
||||
self.bit_count = 0;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_bool(&mut self, probability: u8) -> u8 {
|
||||
pub fn read_bool(&mut self, probability: u8) -> bool {
|
||||
let split = 1 + (((self.range - 1) * u32::from(probability)) >> 8);
|
||||
let bigsplit = split << 8;
|
||||
|
||||
let retval = if self.value >= bigsplit {
|
||||
self.range -= split;
|
||||
self.value -= bigsplit;
|
||||
1
|
||||
true
|
||||
} else {
|
||||
self.range = split;
|
||||
0
|
||||
false
|
||||
};
|
||||
|
||||
while self.range < 128 {
|
||||
@ -663,8 +718,13 @@ impl BoolReader {
|
||||
|
||||
if self.bit_count == 8 {
|
||||
self.bit_count = 0;
|
||||
self.value |= u32::from(self.buf[self.index]);
|
||||
self.index += 1;
|
||||
|
||||
// If no more bits are available, just don't do anything.
|
||||
// This strategy is suggested in the reference implementation of RFC6386 (p.135)
|
||||
if self.index < self.buf.len() {
|
||||
self.value |= u32::from(self.buf[self.index]);
|
||||
self.index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -676,7 +736,7 @@ impl BoolReader {
|
||||
let mut n = n;
|
||||
|
||||
while n != 0 {
|
||||
v = (v << 1) + self.read_bool(128u8);
|
||||
v = (v << 1) + self.read_bool(128u8) as u8;
|
||||
n -= 1;
|
||||
}
|
||||
|
||||
@ -715,27 +775,15 @@ impl BoolReader {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct MacroBlock {
|
||||
bpred: [i8; 16],
|
||||
bpred: [IntraMode; 16],
|
||||
complexity: [u8; 9],
|
||||
luma_mode: i8,
|
||||
chroma_mode: i8,
|
||||
luma_mode: LumaMode,
|
||||
chroma_mode: ChromaMode,
|
||||
segmentid: u8,
|
||||
}
|
||||
|
||||
impl MacroBlock {
|
||||
fn new() -> MacroBlock {
|
||||
MacroBlock {
|
||||
bpred: [0i8; 16],
|
||||
complexity: [0u8; 9],
|
||||
luma_mode: 0,
|
||||
chroma_mode: 0,
|
||||
segmentid: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Representation of the last decoded video frame
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Frame {
|
||||
@ -823,9 +871,9 @@ impl<R: Read> VP8Decoder<R> {
|
||||
/// Create a new decoder.
|
||||
/// The reader must present a raw vp8 bitstream to the decoder
|
||||
pub fn new(r: R) -> VP8Decoder<R> {
|
||||
let f: Frame = Default::default();
|
||||
let s: Segment = Default::default();
|
||||
let m = MacroBlock::new();
|
||||
let f = Frame::default();
|
||||
let s = Segment::default();
|
||||
let m = MacroBlock::default();
|
||||
|
||||
VP8Decoder {
|
||||
r,
|
||||
@ -874,7 +922,7 @@ impl<R: Read> VP8Decoder<R> {
|
||||
for (j, js) in is.iter().enumerate() {
|
||||
for (k, ks) in js.iter().enumerate() {
|
||||
for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
|
||||
if self.b.read_bool(*prob) != 0 {
|
||||
if self.b.read_bool(*prob) {
|
||||
let v = self.b.read_literal(8);
|
||||
self.token_probs[i][j][k][t] = v;
|
||||
}
|
||||
@ -884,33 +932,38 @@ impl<R: Read> VP8Decoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_partitions(&mut self, n: usize) -> io::Result<()> {
|
||||
fn init_partitions(&mut self, n: usize) -> ImageResult<()> {
|
||||
if n > 1 {
|
||||
let mut sizes = Vec::with_capacity(3 * n - 3);
|
||||
try!(
|
||||
self.r
|
||||
.by_ref()
|
||||
.take(3 * n as u64 - 3)
|
||||
.read_to_end(&mut sizes)
|
||||
);
|
||||
let mut sizes = vec![0; 3 * n - 3];
|
||||
self.r.read_exact(sizes.as_mut_slice())?;
|
||||
|
||||
for (i, s) in sizes.chunks(3).enumerate() {
|
||||
let size = u32::from(s[0]) + ((u32::from(s[1])) << 8) + ((u32::from(s[2])) << 8);
|
||||
let mut buf = Vec::with_capacity(size as usize);
|
||||
try!(self.r.by_ref().take(u64::from(size)).read_to_end(&mut buf));
|
||||
let size = {s}.read_u24::<LittleEndian>()
|
||||
.expect("Reading from &[u8] can't fail and the chunk is complete");
|
||||
|
||||
self.partitions[i].init(buf);
|
||||
let mut buf = vec![0; size as usize];
|
||||
self.r.read_exact(buf.as_mut_slice())?;
|
||||
|
||||
self.partitions[i].init(buf)?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut buf = Vec::new();
|
||||
try!(self.r.read_to_end(&mut buf));
|
||||
self.partitions[n - 1].init(buf);
|
||||
self.r.read_to_end(&mut buf)?;
|
||||
self.partitions[n - 1].init(buf)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_quantization_indices(&mut self) {
|
||||
fn dc_quant(index: i32) -> i16 {
|
||||
DC_QUANT[clamp(index, 0, 127) as usize]
|
||||
}
|
||||
|
||||
fn ac_quant(index: i32) -> i16 {
|
||||
AC_QUANT[clamp(index, 0, 127) as usize]
|
||||
}
|
||||
|
||||
let yac_abs = self.b.read_literal(7);
|
||||
let ydc_delta = if self.b.read_flag() {
|
||||
self.b.read_magnitude_and_sign(4)
|
||||
@ -954,14 +1007,15 @@ impl<R: Read> VP8Decoder<R> {
|
||||
i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
|
||||
});
|
||||
|
||||
self.segment[i].ydc = DC_QUANT[clamp(base + ydc_delta, 0, 127) as usize];
|
||||
self.segment[i].yac = AC_QUANT[clamp(base, 0, 127) as usize];
|
||||
self.segment[i].ydc = dc_quant(base + ydc_delta);
|
||||
self.segment[i].yac = ac_quant(base);
|
||||
|
||||
self.segment[i].y2dc = DC_QUANT[clamp(base + y2dc_delta, 0, 127) as usize] * 2;
|
||||
self.segment[i].y2ac = AC_QUANT[clamp(base + y2ac_delta, 0, 127) as usize] * 155 / 100;
|
||||
self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2;
|
||||
// The intermediate result (max`284*155`) can be larger than the `i16` range.
|
||||
self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
|
||||
|
||||
self.segment[i].uvdc = DC_QUANT[clamp(base + uvdc_delta, 0, 127) as usize];
|
||||
self.segment[i].uvac = AC_QUANT[clamp(base + uvac_delta, 0, 127) as usize];
|
||||
self.segment[i].uvdc = dc_quant(base + uvdc_delta);
|
||||
self.segment[i].uvac = ac_quant(base + uvac_delta);
|
||||
|
||||
if self.segment[i].y2ac < 8 {
|
||||
self.segment[i].y2ac = 8;
|
||||
@ -1039,29 +1093,34 @@ impl<R: Read> VP8Decoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_frame_header(&mut self) -> io::Result<()> {
|
||||
let mut tag = [0u8; 3];
|
||||
try!(self.r.read_exact(&mut tag));
|
||||
fn read_frame_header(&mut self) -> ImageResult<()> {
|
||||
let tag = self.r.read_u24::<LittleEndian>()?;
|
||||
|
||||
self.frame.keyframe = tag[0] & 1 == 0;
|
||||
self.frame.version = (tag[0] >> 1) & 7;
|
||||
self.frame.for_display = (tag[0] >> 4) & 1 != 0;
|
||||
self.frame.keyframe = tag & 1 == 0;
|
||||
self.frame.version = ((tag >> 1) & 7) as u8;
|
||||
self.frame.for_display = (tag >> 4) & 1 != 0;
|
||||
|
||||
let first_partition_size =
|
||||
((u32::from(tag[2]) << 16) | (u32::from(tag[1]) << 8) | u32::from(tag[0])) >> 5;
|
||||
let first_partition_size = tag >> 5;
|
||||
|
||||
if self.frame.keyframe {
|
||||
try!(self.r.read_exact(&mut tag));
|
||||
assert_eq!(tag, [0x9d, 0x01, 0x2a]);
|
||||
let mut tag = [0u8; 3];
|
||||
self.r.read_exact(&mut tag)?;
|
||||
|
||||
let w = try!(self.r.read_u16::<LittleEndian>());
|
||||
let h = try!(self.r.read_u16::<LittleEndian>());
|
||||
if tag != [0x9d, 0x01, 0x2a] {
|
||||
return Err(ImageError::FormatError(
|
||||
format!("Invalid magic bytes {:?} for vp8", tag)))
|
||||
}
|
||||
|
||||
let w = self.r.read_u16::<LittleEndian>()?;
|
||||
let h = self.r.read_u16::<LittleEndian>()?;
|
||||
|
||||
self.frame.width = w & 0x3FFF;
|
||||
self.frame.height = h & 0x3FFF;
|
||||
|
||||
self.top = init_top_macroblocks(self.frame.width as usize);
|
||||
self.left = MacroBlock { ..self.top[0] };
|
||||
// Almost always the first macro block, except when non exists (i.e. `width == 0`)
|
||||
self.left = self.top.get(0).cloned()
|
||||
.unwrap_or_else(MacroBlock::default);
|
||||
|
||||
self.mbwidth = (self.frame.width + 15) / 16;
|
||||
self.mbheight = (self.frame.height + 15) / 16;
|
||||
@ -1072,20 +1131,20 @@ impl<R: Read> VP8Decoder<R> {
|
||||
self.left_border = vec![129u8; 1 + 16];
|
||||
}
|
||||
|
||||
let mut buf = Vec::with_capacity(first_partition_size as usize);
|
||||
try!(
|
||||
self.r
|
||||
.by_ref()
|
||||
.take(u64::from(first_partition_size))
|
||||
.read_to_end(&mut buf)
|
||||
);
|
||||
let mut buf = vec![0; first_partition_size as usize];
|
||||
self.r.read_exact(&mut buf)?;
|
||||
|
||||
// initialise binary decoder
|
||||
self.b.init(buf);
|
||||
self.b.init(buf)?;
|
||||
|
||||
if self.frame.keyframe {
|
||||
let color_space = self.b.read_literal(1);
|
||||
self.frame.pixel_type = self.b.read_literal(1);
|
||||
assert_eq!(color_space, 0);
|
||||
|
||||
if color_space != 0 {
|
||||
return Err(ImageError::FormatError(
|
||||
format!("Only YUV color space is specified.")))
|
||||
}
|
||||
}
|
||||
|
||||
self.segments_enabled = self.b.read_flag();
|
||||
@ -1104,13 +1163,15 @@ impl<R: Read> VP8Decoder<R> {
|
||||
|
||||
self.num_partitions = (1usize << self.b.read_literal(2) as usize) as u8;
|
||||
let num_partitions = self.num_partitions as usize;
|
||||
try!(self.init_partitions(num_partitions));
|
||||
self.init_partitions(num_partitions)?;
|
||||
|
||||
self.read_quantization_indices();
|
||||
|
||||
if !self.frame.keyframe {
|
||||
// 9.7 refresh golden frame and altref frame
|
||||
panic!("unimplemented")
|
||||
return Err(ImageError::UnsupportedError(
|
||||
"Frames that are not keyframes are not supported".into()))
|
||||
// FIXME: support this?
|
||||
} else {
|
||||
// Refresh entropy probs ?????
|
||||
let _ = self.b.read_literal(1);
|
||||
@ -1129,7 +1190,9 @@ impl<R: Read> VP8Decoder<R> {
|
||||
// 9.10 remaining frame data
|
||||
self.prob_intra = 0;
|
||||
|
||||
panic!("unimplemented")
|
||||
return Err(ImageError::UnsupportedError(
|
||||
"Frames that are not keyframes are not supported".into()))
|
||||
// FIXME: support this?
|
||||
} else {
|
||||
// Reset motion vectors
|
||||
}
|
||||
@ -1137,8 +1200,8 @@ impl<R: Read> VP8Decoder<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_macroblock_header(&mut self, mbx: usize) -> (bool, MacroBlock) {
|
||||
let mut mb = MacroBlock::new();
|
||||
fn read_macroblock_header(&mut self, mbx: usize) -> ImageResult<(bool, MacroBlock)> {
|
||||
let mut mb = MacroBlock::default();
|
||||
|
||||
mb.segmentid = if self.segments_enabled && self.segments_update_map {
|
||||
self.b
|
||||
@ -1148,67 +1211,75 @@ impl<R: Read> VP8Decoder<R> {
|
||||
};
|
||||
|
||||
let skip_coeff = if self.prob_skip_false.is_some() {
|
||||
1 == self.b.read_bool(*self.prob_skip_false.as_ref().unwrap())
|
||||
self.b.read_bool(*self.prob_skip_false.as_ref().unwrap())
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let inter_predicted = if !self.frame.keyframe {
|
||||
1 == self.b.read_bool(self.prob_intra)
|
||||
self.b.read_bool(self.prob_intra)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if inter_predicted {
|
||||
panic!("inter prediction not implemented");
|
||||
return Err(ImageError::UnsupportedError(
|
||||
"VP8 inter prediction is not implemented yet".into()));
|
||||
}
|
||||
|
||||
if self.frame.keyframe {
|
||||
// intra prediction
|
||||
mb.luma_mode = self.b
|
||||
let luma = self.b
|
||||
.read_with_tree(&KEYFRAME_YMODE_TREE, &KEYFRAME_YMODE_PROBS, 0);
|
||||
mb.luma_mode = LumaMode::from_i8(luma)
|
||||
.ok_or_else(|| ImageError::FormatError(
|
||||
format!("Invalid luma prediction mode {}", luma))
|
||||
)?;
|
||||
|
||||
if mb.luma_mode == B_PRED {
|
||||
for y in 0usize..4 {
|
||||
for x in 0usize..4 {
|
||||
let top = self.top[mbx].bpred[12 + x];
|
||||
let left = self.left.bpred[y];
|
||||
let bmode = self.b.read_with_tree(
|
||||
&KEYFRAME_BPRED_MODE_TREE,
|
||||
&KEYFRAME_BPRED_MODE_PROBS[top as usize][left as usize],
|
||||
0,
|
||||
);
|
||||
mb.bpred[x + y * 4] = bmode;
|
||||
match mb.luma_mode.into_intra() {
|
||||
// `LumaMode::B` - This is predicted individually
|
||||
None => {
|
||||
for y in 0usize..4 {
|
||||
for x in 0usize..4 {
|
||||
let top = self.top[mbx].bpred[12 + x];
|
||||
let left = self.left.bpred[y];
|
||||
let intra = self.b.read_with_tree(
|
||||
&KEYFRAME_BPRED_MODE_TREE,
|
||||
&KEYFRAME_BPRED_MODE_PROBS[top as usize][left as usize],
|
||||
0,
|
||||
);
|
||||
let bmode = IntraMode::from_i8(intra)
|
||||
.ok_or_else(|| ImageError::FormatError(
|
||||
format!("Invalid intra prediction mode {}", intra))
|
||||
)?;
|
||||
mb.bpred[x + y * 4] = bmode;
|
||||
|
||||
self.top[mbx].bpred[12 + x] = bmode;
|
||||
self.left.bpred[y] = bmode;
|
||||
self.top[mbx].bpred[12 + x] = bmode;
|
||||
self.left.bpred[y] = bmode;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(mode) => {
|
||||
for i in 0usize..4 {
|
||||
mb.bpred[12 + i] = mode;
|
||||
self.left.bpred[i] = mode;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in 0usize..4 {
|
||||
let mode = match mb.luma_mode {
|
||||
DC_PRED => B_DC_PRED,
|
||||
V_PRED => B_VE_PRED,
|
||||
H_PRED => B_HE_PRED,
|
||||
TM_PRED => B_TM_PRED,
|
||||
_ => panic!("unreachable"),
|
||||
};
|
||||
|
||||
mb.bpred[12 + i] = mode;
|
||||
self.left.bpred[i] = mode;
|
||||
}
|
||||
}
|
||||
|
||||
mb.chroma_mode =
|
||||
self.b
|
||||
.read_with_tree(&KEYFRAME_UV_MODE_TREE, &KEYFRAME_UV_MODE_PROBS, 0);
|
||||
let chroma = self.b
|
||||
.read_with_tree(&KEYFRAME_UV_MODE_TREE, &KEYFRAME_UV_MODE_PROBS, 0);
|
||||
mb.chroma_mode = ChromaMode::from_i8(chroma)
|
||||
.ok_or_else(|| ImageError::FormatError(
|
||||
format!("Invalid chroma prediction mode {}", chroma))
|
||||
)?;
|
||||
}
|
||||
|
||||
self.top[mbx].chroma_mode = mb.chroma_mode;
|
||||
self.top[mbx].luma_mode = mb.luma_mode;
|
||||
self.top[mbx].bpred = mb.bpred;
|
||||
|
||||
(skip_coeff, mb)
|
||||
Ok((skip_coeff, mb))
|
||||
}
|
||||
|
||||
fn intra_predict(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
|
||||
@ -1218,15 +1289,14 @@ impl<R: Read> VP8Decoder<R> {
|
||||
let mut ws = create_border(mbx, mby, mw, &self.top_border, &self.left_border);
|
||||
|
||||
match mb.luma_mode {
|
||||
V_PRED => predict_vpred(&mut ws, 16, 1, 1, stride),
|
||||
H_PRED => predict_hpred(&mut ws, 16, 1, 1, stride),
|
||||
TM_PRED => predict_tmpred(&mut ws, 16, 1, 1, stride),
|
||||
DC_PRED => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
|
||||
B_PRED => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
|
||||
_ => panic!("unknown luma intra prediction mode"),
|
||||
LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
|
||||
LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
|
||||
LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
|
||||
LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
|
||||
LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
|
||||
}
|
||||
|
||||
if mb.luma_mode != B_PRED {
|
||||
if mb.luma_mode != LumaMode::B {
|
||||
for y in 0usize..4 {
|
||||
for x in 0usize..4 {
|
||||
let i = x + y * 4;
|
||||
@ -1246,17 +1316,9 @@ impl<R: Read> VP8Decoder<R> {
|
||||
self.left_border[i + 1] = ws[(i + 1) * stride + 16];
|
||||
}
|
||||
|
||||
let ylength = if mby < self.mbheight as usize - 1 || self.frame.height % 16 == 0 {
|
||||
16usize
|
||||
} else {
|
||||
(16 - (self.frame.height as usize & 15)) % 16
|
||||
};
|
||||
|
||||
let xlength = if mbx < self.mbwidth as usize - 1 || self.frame.width % 16 == 0 {
|
||||
16usize
|
||||
} else {
|
||||
(16 - (self.frame.width as usize & 15)) % 16
|
||||
};
|
||||
// Length is the remainder to the border, but maximally the current chunk.
|
||||
let ylength = cmp::min(self.frame.height as usize - mby*16, 16);
|
||||
let xlength = cmp::min(self.frame.width as usize - mbx*16, 16);
|
||||
|
||||
for y in 0usize..ylength {
|
||||
for x in 0usize..xlength {
|
||||
@ -1301,16 +1363,16 @@ impl<R: Read> VP8Decoder<R> {
|
||||
continue;
|
||||
}
|
||||
|
||||
literal @ DCT_1...DCT_4 => i16::from(literal),
|
||||
literal @ DCT_1..=DCT_4 => i16::from(literal),
|
||||
|
||||
category @ DCT_CAT1...DCT_CAT6 => {
|
||||
category @ DCT_CAT1..=DCT_CAT6 => {
|
||||
let t = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
|
||||
|
||||
let mut extra = 0i16;
|
||||
let mut j = 0;
|
||||
|
||||
while t[j] > 0 {
|
||||
extra = extra + extra + i16::from(self.partitions[p].read_bool(t[j]));
|
||||
extra = extra + extra + self.partitions[p].read_bool(t[j]) as i16;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
@ -1330,7 +1392,7 @@ impl<R: Read> VP8Decoder<R> {
|
||||
2
|
||||
};
|
||||
|
||||
if self.partitions[p].read_bool(128) == 1 {
|
||||
if self.partitions[p].read_bool(128) {
|
||||
abs_value = -abs_value;
|
||||
}
|
||||
|
||||
@ -1346,7 +1408,7 @@ impl<R: Read> VP8Decoder<R> {
|
||||
fn read_residual_data(&mut self, mb: &MacroBlock, mbx: usize, p: usize) -> [i32; 384] {
|
||||
let sindex = mb.segmentid as usize;
|
||||
let mut blocks = [0i32; 384];
|
||||
let mut plane = if mb.luma_mode == B_PRED { 3 } else { 1 };
|
||||
let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
|
||||
|
||||
if plane == 1 {
|
||||
let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
|
||||
@ -1421,19 +1483,19 @@ impl<R: Read> VP8Decoder<R> {
|
||||
}
|
||||
|
||||
/// Decodes the current frame and returns a reference to it
|
||||
pub fn decode_frame(&mut self) -> io::Result<&Frame> {
|
||||
try!(self.read_frame_header());
|
||||
pub fn decode_frame(&mut self) -> ImageResult<&Frame> {
|
||||
self.read_frame_header()?;
|
||||
|
||||
for mby in 0..self.mbheight as usize {
|
||||
let p = mby % self.num_partitions as usize;
|
||||
self.left = MacroBlock::new();
|
||||
self.left = MacroBlock::default();
|
||||
|
||||
for mbx in 0..self.mbwidth as usize {
|
||||
let (skip, mb) = self.read_macroblock_header(mbx);
|
||||
let (skip, mb) = self.read_macroblock_header(mbx)?;
|
||||
let blocks = if !skip {
|
||||
self.read_residual_data(&mb, mbx, p)
|
||||
} else {
|
||||
if mb.luma_mode != B_PRED {
|
||||
if mb.luma_mode != LumaMode::B {
|
||||
self.left.complexity[0] = 0;
|
||||
self.top[mbx].complexity[0] = 0;
|
||||
}
|
||||
@ -1456,17 +1518,88 @@ impl<R: Read> VP8Decoder<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LumaMode {
|
||||
fn from_i8(val: i8) -> Option<Self> {
|
||||
Some(match val {
|
||||
DC_PRED => LumaMode::DC,
|
||||
V_PRED => LumaMode::V,
|
||||
H_PRED => LumaMode::H,
|
||||
TM_PRED => LumaMode::TM,
|
||||
B_PRED => LumaMode::B,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn into_intra(self) -> Option<IntraMode> {
|
||||
Some(match self {
|
||||
LumaMode::DC => IntraMode::DC,
|
||||
LumaMode::V => IntraMode::VE,
|
||||
LumaMode::H => IntraMode::HE,
|
||||
LumaMode::TM => IntraMode::TM,
|
||||
LumaMode::B => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LumaMode {
|
||||
fn default() -> Self {
|
||||
LumaMode::DC
|
||||
}
|
||||
}
|
||||
|
||||
impl ChromaMode {
|
||||
fn from_i8(val: i8) -> Option<Self> {
|
||||
Some(match val {
|
||||
DC_PRED => ChromaMode::DC,
|
||||
V_PRED => ChromaMode::V,
|
||||
H_PRED => ChromaMode::H,
|
||||
TM_PRED => ChromaMode::TM,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ChromaMode {
|
||||
fn default() -> Self {
|
||||
ChromaMode::DC
|
||||
}
|
||||
}
|
||||
|
||||
impl IntraMode {
|
||||
fn from_i8(val: i8) -> Option<Self> {
|
||||
Some(match val {
|
||||
B_DC_PRED => IntraMode::DC,
|
||||
B_TM_PRED => IntraMode::TM,
|
||||
B_VE_PRED => IntraMode::VE,
|
||||
B_HE_PRED => IntraMode::HE,
|
||||
B_LD_PRED => IntraMode::LD,
|
||||
B_RD_PRED => IntraMode::RD,
|
||||
B_VR_PRED => IntraMode::VR,
|
||||
B_VL_PRED => IntraMode::VL,
|
||||
B_HD_PRED => IntraMode::HD,
|
||||
B_HU_PRED => IntraMode::HU,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IntraMode {
|
||||
fn default() -> Self {
|
||||
IntraMode::DC
|
||||
}
|
||||
}
|
||||
|
||||
fn init_top_macroblocks(width: usize) -> Vec<MacroBlock> {
|
||||
let mb_width = (width + 15) / 16;
|
||||
|
||||
let mb = MacroBlock {
|
||||
// Section 11.3 #3
|
||||
bpred: [B_DC_PRED; 16],
|
||||
luma_mode: DC_PRED,
|
||||
..MacroBlock::new()
|
||||
bpred: [IntraMode::DC; 16],
|
||||
luma_mode: LumaMode::DC,
|
||||
.. MacroBlock::default()
|
||||
};
|
||||
|
||||
(0..mb_width).map(|_| mb).collect()
|
||||
vec![mb; mb_width]
|
||||
}
|
||||
|
||||
fn create_border(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] {
|
||||
@ -1547,7 +1680,7 @@ fn add_residue(pblock: &mut [u8], rblock: &[i32], y0: usize, x0: usize, stride:
|
||||
}
|
||||
}
|
||||
|
||||
fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[i8], resdata: &[i32]) {
|
||||
fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) {
|
||||
for sby in 0usize..4 {
|
||||
for sbx in 0usize..4 {
|
||||
let i = sbx + sby * 4;
|
||||
@ -1556,17 +1689,16 @@ fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[i8], resdata: &[i32]) {
|
||||
let rb = &resdata[i * 16..i * 16 + 16];
|
||||
|
||||
match modes[i] {
|
||||
B_TM_PRED => predict_tmpred(ws, 4, x0, y0, stride),
|
||||
B_VE_PRED => predict_bvepred(ws, x0, y0, stride),
|
||||
B_HE_PRED => predict_bhepred(ws, x0, y0, stride),
|
||||
B_DC_PRED => predict_bdcpred(ws, x0, y0, stride),
|
||||
B_LD_PRED => predict_bldpred(ws, x0, y0, stride),
|
||||
B_RD_PRED => predict_brdpred(ws, x0, y0, stride),
|
||||
B_VR_PRED => predict_bvrpred(ws, x0, y0, stride),
|
||||
B_VL_PRED => predict_bvlpred(ws, x0, y0, stride),
|
||||
B_HD_PRED => predict_bhdpred(ws, x0, y0, stride),
|
||||
B_HU_PRED => predict_bhupred(ws, x0, y0, stride),
|
||||
_ => panic!("unknown intra bmode"),
|
||||
IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride),
|
||||
IntraMode::VE => predict_bvepred(ws, x0, y0, stride),
|
||||
IntraMode::HE => predict_bhepred(ws, x0, y0, stride),
|
||||
IntraMode::DC => predict_bdcpred(ws, x0, y0, stride),
|
||||
IntraMode::LD => predict_bldpred(ws, x0, y0, stride),
|
||||
IntraMode::RD => predict_brdpred(ws, x0, y0, stride),
|
||||
IntraMode::VR => predict_bvrpred(ws, x0, y0, stride),
|
||||
IntraMode::VL => predict_bvlpred(ws, x0, y0, stride),
|
||||
IntraMode::HD => predict_bhdpred(ws, x0, y0, stride),
|
||||
IntraMode::HU => predict_bhupred(ws, x0, y0, stride),
|
||||
}
|
||||
|
||||
add_residue(ws, rb, y0, x0, stride);
|
||||
|
2
third_party/rust/png/.cargo-checksum.json
vendored
2
third_party/rust/png/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"8cc6eb1d08623955951841761c9757e67a43048d6cb40197ebabf2de1f6c46d4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"4556c29a1c1dd656eb7a85bb1929f4112c7d8525216fc508e616bef4036ef023","examples/pngcheck.rs":"9eea856ab45e0daf3f470f7f86d0c3521cf3de7e06f0fcc8764800fa57ffd86d","examples/show.rs":"0cf8a74a1b8a0c350fee5eacfee082607e8adcd51968a1460ee6305d83041d19","src/chunk.rs":"f8aa01e68683b5cd41ac2580ac11f2d6a6190c52007e3f115dc5b7c3b0354e63","src/common.rs":"4f80198a5131de872a19e0b443d88def80d1688f4f1317cfd05a6b773564a48e","src/crc.rs":"7136e3ae5564db1aadfd45c3c4d65d1d41ede797b2e8be7ca1e731bd567d04bc","src/decoder/mod.rs":"e4d7e58c5f80ccccd445d22278ce46a77c9f64db8d0a8c20530917fcd6df3a1a","src/decoder/stream.rs":"917285c321e3de1b07b6aa5943bfef315e9b7bdc8035dca65b5c8c4b605b4796","src/encoder.rs":"ff0582366827a84a9a742d1781fcc41c005d34b422edeef9e063804f4b9a86c2","src/filter.rs":"74015c3e328bc0b5c03826f971ffb48f16903488f54ce16b0245b5a1467c0c08","src/lib.rs":"be7360d6f5c278f78da90e578b14bae6a4fc1e249538ff5e6aaf1d75d1bdea34","src/traits.rs":"f326ebcba17b87b609b564ff2aa4aaf1f5de4dcff991aa4d21f3d9b0ba39affc","src/utils.rs":"c5b45039c9903962842544d8ef5203a1ce820cb8010bd1bf8cc1f517d45ef160"},"package":"9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"}
|
||||
{"files":{"Cargo.toml":"cbabe74b9508336598dee4e2736e644607fbaa05b1aa7b03cf324c14c02c747e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"a29453dab1a440374ed18881bfbb73651e2b84c35eabc0a7b293ab553ef345f4","benches/README.md":"0c60c3d497abdf6c032863aa47da41bc6bb4f5ff696d45dec0e6eb33459b14b0","benches/decoder.rs":"81a13f5c731f674cc21a6aa472bcf4cc6c3581a41b1e002fa3996fc9a6e0dfe5","examples/pngcheck.rs":"191ff0b61734a75befd0d3ecd3f39226e9f3ef89a5d7a16870808f5ebf0e054d","examples/show.rs":"22be41150fa02d42500c48920cf3b7277090680e336ab8744aac0cece8bccc68","src/chunk.rs":"f8aa01e68683b5cd41ac2580ac11f2d6a6190c52007e3f115dc5b7c3b0354e63","src/common.rs":"a0bc64f16cfdf511925a2869d9fda70ed07272a8278c1d2db142821babd4c931","src/decoder/mod.rs":"ec173948f4cd09837b5e59b30ba209a0b96d2cc23570152c4850891058632eff","src/decoder/stream.rs":"28ef3d00fc65463019f22e95b568b9776d6249de388d2af2af116017330a6bdd","src/encoder.rs":"8bc2f8a5f6f45a59de4933d230f3340f11c934d2c5f5493dbc202505d398319f","src/filter.rs":"7de56800200b15b7a6bf79eefb8771ae29c37accce8a1044f37620153060f8ba","src/lib.rs":"1d56a30f6283bbeaeb2cf7c03061b2081e8f85284b206104d08865a801b944e9","src/traits.rs":"3afe302164f1d5ffdc0482489332c6fc78120ce19c0a7db5a1f4bda0326d8f62","src/utils.rs":"03af618a3d2fe6d49828a7afc876d4561472588f542bb49191735b93f533c921"},"package":"8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602"}
|
21
third_party/rust/png/Cargo.toml
vendored
21
third_party/rust/png/Cargo.toml
vendored
@ -3,7 +3,7 @@
|
||||
# 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
|
||||
# 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
|
||||
@ -11,25 +11,27 @@
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "png"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
authors = ["nwin <nwin@users.noreply.github.com>"]
|
||||
exclude = ["tests/*"]
|
||||
description = "PNG decoding and encoding library in pure Rust"
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/PistonDevelopers/image-png.git"
|
||||
categories = ["multimedia::images"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/image-rs/image-png.git"
|
||||
[dependencies.bitflags]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.crc32fast]
|
||||
version = "1.2.0"
|
||||
|
||||
[dependencies.deflate]
|
||||
version = "0.7.2"
|
||||
version = "0.7.12"
|
||||
optional = true
|
||||
|
||||
[dependencies.inflate]
|
||||
version = "0.4.2"
|
||||
|
||||
[dependencies.num-iter]
|
||||
version = "0.1.32"
|
||||
[dev-dependencies.getopts]
|
||||
version = "0.2.14"
|
||||
|
||||
@ -39,7 +41,7 @@ features = ["glutin"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.glob]
|
||||
version = "0.2.11"
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.5.5"
|
||||
@ -48,6 +50,7 @@ version = "0.5.5"
|
||||
version = "0.4"
|
||||
|
||||
[features]
|
||||
benchmarks = []
|
||||
default = ["png-encoding"]
|
||||
png-encoding = ["deflate"]
|
||||
unstable = []
|
||||
|
25
third_party/rust/png/README.md
vendored
25
third_party/rust/png/README.md
vendored
@ -1,11 +1,26 @@
|
||||
# PNG Decoder/Encoder
|
||||
[![Build Status](https://travis-ci.org/PistonDevelopers/image-png.svg?branch=master)](https://travis-ci.org/PistonDevelopers/image-png)
|
||||
[![Crates.io](https://docs.rs/png/badge.svg)](https://docs.rs/png)
|
||||
[![Build Status](https://travis-ci.org/image-rs/image-png.svg?branch=master)](https://travis-ci.org/image-rs/image-png)
|
||||
[![Documentation](https://docs.rs/png/badge.svg)](https://docs.rs/png)
|
||||
[![Crates.io](https://img.shields.io/crates/v/png.svg)](https://crates.io/crates/png)
|
||||
![Lines of Code](https://tokei.rs/b1/github/PistonDevelopers/image-png)
|
||||
[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/PistonDevelopers/image-png)
|
||||
![Lines of Code](https://tokei.rs/b1/github/image-rs/image-png)
|
||||
[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/image-rs/image-png)
|
||||
|
||||
PNG decoder/encoder in pure Rust. Currently `pngcheck` is the most usable part. Build with `cargo build --release --example pngcheck`.
|
||||
PNG decoder/encoder in pure Rust.
|
||||
|
||||
It contains all features required to handle the entirety of [the PngSuite by
|
||||
Willem van Schack][PngSuite].
|
||||
|
||||
[PngSuite]: http://www.schaik.com/pngsuite2011/pngsuite.html
|
||||
|
||||
## pngcheck
|
||||
|
||||
The `pngcheck` utility is a small demonstration binary that checks and prints
|
||||
metadata on every `.png` image provided via parameter. You can run it (for
|
||||
example on the test directories) with
|
||||
|
||||
```bash
|
||||
cargo run --release --example pngcheck ./tests/pngsuite/*
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
|
6
third_party/rust/png/benches/README.md
vendored
Normal file
6
third_party/rust/png/benches/README.md
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Getting started with benchmarking
|
||||
|
||||
To run the benchmarks you need a nightly rust toolchain.
|
||||
Then you launch it with
|
||||
|
||||
rustup run nightly cargo bench --features=benchmarks
|
25
third_party/rust/png/benches/decoder.rs
vendored
Normal file
25
third_party/rust/png/benches/decoder.rs
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
#![cfg(feature = "benchmarks")]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate png;
|
||||
extern crate test;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use png::Decoder;
|
||||
|
||||
#[bench]
|
||||
fn bench_big(b: &mut test::Bencher) {
|
||||
let mut data = Vec::new();
|
||||
File::open("tests/pngsuite/PngSuite.png").unwrap().read_to_end(&mut data).unwrap();
|
||||
let decoder = Decoder::new(&*data);
|
||||
let (info, _) = decoder.read_info().unwrap();
|
||||
let mut image = vec![0; info.buffer_size()];
|
||||
b.iter(|| {
|
||||
let decoder = Decoder::new(&*data);
|
||||
let (_, mut decoder) = decoder.read_info().unwrap();
|
||||
test::black_box(decoder.next_frame(&mut image)).unwrap();
|
||||
});
|
||||
b.bytes = info.buffer_size() as u64
|
||||
}
|
153
third_party/rust/png/examples/pngcheck.rs
vendored
153
third_party/rust/png/examples/pngcheck.rs
vendored
@ -14,7 +14,7 @@ use std::env;
|
||||
use getopts::{Matches, Options, ParsingStyle};
|
||||
use term::{color, Attr};
|
||||
|
||||
fn parse_args() -> Option<Matches> {
|
||||
fn parse_args() -> Matches {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("c", "", "colorize output (for ANSI terminals)")
|
||||
@ -24,12 +24,12 @@ fn parse_args() -> Option<Matches> {
|
||||
.parsing_style(ParsingStyle::StopAtFirstFree);
|
||||
if args.len() > 1 {
|
||||
match opts.parse(&args[1..]) {
|
||||
Ok(matches) => return Some(matches),
|
||||
Ok(matches) => return matches,
|
||||
Err(err) => println!("{}", err)
|
||||
}
|
||||
}
|
||||
println!("{}", opts.usage(&format!("Usage: pngcheck [-cpt] [file ...]")));
|
||||
None
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@ -75,15 +75,15 @@ fn final_channels(c: png::ColorType, trns: bool) -> u8 {
|
||||
fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
// TODO improve performance by resusing allocations from decoder
|
||||
use png::Decoded::*;
|
||||
let mut t = try!(term::stdout().ok_or(io::Error::new(
|
||||
let mut t = term::stdout().ok_or(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"could not open terminal"
|
||||
)));
|
||||
))?;
|
||||
let mut data = vec![0; 10*1024];
|
||||
let data_p = data.as_mut_ptr();
|
||||
let mut reader = io::BufReader::new(try!(File::open(&fname)));
|
||||
let mut reader = io::BufReader::new(File::open(&fname)?);
|
||||
let fname = fname.as_ref().to_string_lossy();
|
||||
let n = try!(reader.read(&mut data));
|
||||
let n = reader.read(&mut data)?;
|
||||
let mut buf = &data[..n];
|
||||
let mut pos = 0;
|
||||
let mut decoder = png::StreamingDecoder::new();
|
||||
@ -107,18 +107,18 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
});
|
||||
);
|
||||
let display_error = |err| -> Result<_, io::Error> {
|
||||
let mut t = try!(term::stdout().ok_or(io::Error::new(
|
||||
let mut t = term::stdout().ok_or(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"could not open terminal"
|
||||
)));
|
||||
))?;
|
||||
if c.verbose {
|
||||
if c.color {
|
||||
print!(": ");
|
||||
try!(t.fg(color::RED));
|
||||
try!(writeln!(t, "{}", err));
|
||||
try!(t.attr(Attr::Bold));
|
||||
try!(write!(t, "ERRORS DETECTED"));
|
||||
try!(t.reset());
|
||||
t.fg(color::RED)?;
|
||||
writeln!(t, "{}", err)?;
|
||||
t.attr(Attr::Bold)?;
|
||||
write!(t, "ERRORS DETECTED")?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
println!(": {}", err);
|
||||
print!("ERRORS DETECTED")
|
||||
@ -126,22 +126,22 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
println!(" in {}", fname);
|
||||
} else {
|
||||
if !c.quiet { if c.color {
|
||||
try!(t.fg(color::RED));
|
||||
try!(t.attr(Attr::Bold));
|
||||
try!(write!(t, "ERROR"));
|
||||
try!(t.reset());
|
||||
try!(write!(t, ": "));
|
||||
try!(t.fg(color::YELLOW));
|
||||
try!(writeln!(t, "{}", fname));
|
||||
try!(t.reset());
|
||||
t.fg(color::RED)?;
|
||||
t.attr(Attr::Bold)?;
|
||||
write!(t, "ERROR")?;
|
||||
t.reset()?;
|
||||
write!(t, ": ")?;
|
||||
t.fg(color::YELLOW)?;
|
||||
writeln!(t, "{}", fname)?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
println!("ERROR: {}", fname)
|
||||
}}
|
||||
print!("{}: ", fname);
|
||||
if c.color {
|
||||
try!(t.fg(color::RED));
|
||||
try!(writeln!(t, "{}", err));
|
||||
try!(t.reset());
|
||||
t.fg(color::RED)?;
|
||||
writeln!(t, "{}", err)?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
println!("{}", err);
|
||||
}
|
||||
@ -153,9 +153,9 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
if c.verbose {
|
||||
print!("File: ");
|
||||
if c.color {
|
||||
try!(t.attr(Attr::Bold));
|
||||
try!(write!(t, "{}", fname));
|
||||
try!(t.reset());
|
||||
t.attr(Attr::Bold)?;
|
||||
write!(t, "{}", fname)?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
print!("{}", fname);
|
||||
}
|
||||
@ -165,27 +165,34 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
loop {
|
||||
if buf.len() == 0 {
|
||||
// circumvent borrow checker
|
||||
let n = try!(reader.read(unsafe {
|
||||
assert!(!data.is_empty());
|
||||
let n = reader.read(unsafe {
|
||||
::std::slice::from_raw_parts_mut(data_p, data.len())
|
||||
}));
|
||||
})?;
|
||||
|
||||
// EOF
|
||||
if n == 0 {
|
||||
println!("ERROR: premature end of file {}", fname);
|
||||
break;
|
||||
}
|
||||
buf = &data[..n];
|
||||
}
|
||||
match decoder.update(buf, &mut Vec::new()) {
|
||||
Ok((_, ImageEnd)) => {
|
||||
if !have_idat {
|
||||
try!(display_error(png::DecodingError::Format("IDAT chunk missing".into())));
|
||||
display_error(png::DecodingError::Format("IDAT chunk missing".into()))?;
|
||||
break;
|
||||
}
|
||||
if !c.verbose && !c.quiet {
|
||||
if c.color {
|
||||
try!(t.fg(color::GREEN));
|
||||
try!(t.attr(Attr::Bold));
|
||||
try!(write!(t, "OK"));
|
||||
try!(t.reset());
|
||||
try!(write!(t, ": "));
|
||||
try!(t.fg(color::YELLOW));
|
||||
try!(write!(t, "{}", fname));
|
||||
try!(t.reset());
|
||||
t.fg(color::GREEN)?;
|
||||
t.attr(Attr::Bold)?;
|
||||
write!(t, "OK")?;
|
||||
t.reset()?;
|
||||
write!(t, ": ")?;
|
||||
t.fg(color::YELLOW)?;
|
||||
write!(t, "{}", fname)?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
print!("OK: {}", fname)
|
||||
}
|
||||
@ -201,10 +208,10 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
} else if !c.quiet {
|
||||
println!("");
|
||||
if c.color {
|
||||
try!(t.fg(color::GREEN));
|
||||
try!(t.attr(Attr::Bold));
|
||||
try!(write!(t, "No errors detected "));
|
||||
try!(t.reset());
|
||||
t.fg(color::GREEN)?;
|
||||
t.attr(Attr::Bold)?;
|
||||
write!(t, "No errors detected ")?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
print!("No errors detected ");
|
||||
}
|
||||
@ -236,9 +243,9 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
println!("");
|
||||
print!(" chunk ");
|
||||
if c.color {
|
||||
try!(t.fg(color::YELLOW));
|
||||
try!(write!(t, "{}", chunk));
|
||||
try!(t.reset());
|
||||
t.fg(color::YELLOW)?;
|
||||
write!(t, "{}", chunk)?;
|
||||
t.reset()?;
|
||||
} else {
|
||||
print!("{}", chunk)
|
||||
}
|
||||
@ -323,34 +330,32 @@ fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Some(m) = parse_args() {
|
||||
let config = Config {
|
||||
quiet: m.opt_present("q"),
|
||||
verbose: m.opt_present("v"),
|
||||
color: m.opt_present("c")
|
||||
let m = parse_args();
|
||||
|
||||
let config = Config {
|
||||
quiet: m.opt_present("q"),
|
||||
verbose: m.opt_present("v"),
|
||||
color: m.opt_present("c")
|
||||
};
|
||||
|
||||
for file in m.free {
|
||||
let result = if file.contains("*") {
|
||||
glob::glob(&file).map_err(|err| {
|
||||
io::Error::new(io::ErrorKind::Other, err)
|
||||
}).and_then(|mut glob| glob.try_for_each(|entry| {
|
||||
entry.map_err(|err| {
|
||||
io::Error::new(io::ErrorKind::Other, err)
|
||||
}).and_then(|file| {
|
||||
check_image(config, file)
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
check_image(config, &file)
|
||||
};
|
||||
for file in m.free {
|
||||
match if file.contains("*") {
|
||||
(|| -> io::Result<_> {
|
||||
for entry in try!(glob::glob(&file).map_err(|err| {
|
||||
io::Error::new(io::ErrorKind::Other, err.msg)
|
||||
})) {
|
||||
try!(check_image(config, try!(entry.map_err(|_| {
|
||||
io::Error::new(io::ErrorKind::Other, "glob error")
|
||||
}))))
|
||||
}
|
||||
Ok(())
|
||||
})()
|
||||
} else {
|
||||
check_image(config, &file)
|
||||
} {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
println!("{}: {}", file, err);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result.unwrap_or_else(|err| {
|
||||
println!("{}: {}", file, err);
|
||||
std::process::exit(1)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
16
third_party/rust/png/examples/show.rs
vendored
16
third_party/rust/png/examples/show.rs
vendored
@ -17,10 +17,10 @@ use glium::backend::glutin::Display;
|
||||
/// Load the image using `png`
|
||||
fn load_image(path: &path::PathBuf) -> io::Result<RawImage2d<'static, u8>> {
|
||||
use png::ColorType::*;
|
||||
let decoder = png::Decoder::new(try!(File::open(path)));
|
||||
let (info, mut reader) = try!(decoder.read_info());
|
||||
let decoder = png::Decoder::new(File::open(path)?);
|
||||
let (info, mut reader) = decoder.read_info()?;
|
||||
let mut img_data = vec![0; info.buffer_size()];
|
||||
try!(reader.next_frame(&mut img_data));
|
||||
reader.next_frame(&mut img_data)?;
|
||||
|
||||
let (data, format) = match info.color_type {
|
||||
RGB => (img_data, ClientFormat::U8U8U8),
|
||||
@ -61,7 +61,7 @@ fn main_loop(files: Vec<path::PathBuf>) -> io::Result<()> {
|
||||
use glium::glutin::{KeyboardInput, WindowEvent};
|
||||
|
||||
let mut files = files.iter();
|
||||
let image = try!(load_image(files.next().unwrap()));
|
||||
let image = load_image(files.next().unwrap())?;
|
||||
|
||||
let mut events_loop = glutin::EventsLoop::new();
|
||||
let window = glutin::WindowBuilder::new();
|
||||
@ -169,12 +169,12 @@ fn main() {
|
||||
for file in args.iter().skip(1) {
|
||||
match if file.contains("*") {
|
||||
(|| -> io::Result<_> {
|
||||
for entry in try!(glob::glob(&file).map_err(|err| {
|
||||
for entry in glob::glob(&file).map_err(|err| {
|
||||
io::Error::new(io::ErrorKind::Other, err.msg)
|
||||
})) {
|
||||
files.push(try!(entry.map_err(|_| {
|
||||
})? {
|
||||
files.push(entry.map_err(|_| {
|
||||
io::Error::new(io::ErrorKind::Other, "glob error")
|
||||
})))
|
||||
})?)
|
||||
}
|
||||
Ok(())
|
||||
})()
|
||||
|
162
third_party/rust/png/src/common.rs
vendored
162
third_party/rust/png/src/common.rs
vendored
@ -1,7 +1,9 @@
|
||||
//! Common types shared between the encoder and decoder
|
||||
extern crate deflate;
|
||||
use filter;
|
||||
use crate::filter;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Describes the layout of samples in a pixel
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum ColorType {
|
||||
@ -92,8 +94,74 @@ impl Unit {
|
||||
}
|
||||
}
|
||||
|
||||
/// How to reset buffer of an animated png (APNG) at the end of a frame.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum DisposeOp {
|
||||
/// Leave the buffer unchanged.
|
||||
None = 0,
|
||||
/// Clear buffer with the background color.
|
||||
Background = 1,
|
||||
/// Reset the buffer to the state before the current frame.
|
||||
Previous = 2,
|
||||
}
|
||||
|
||||
impl DisposeOp {
|
||||
/// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
|
||||
pub fn from_u8(n: u8) -> Option<DisposeOp> {
|
||||
match n {
|
||||
0 => Some(DisposeOp::None),
|
||||
1 => Some(DisposeOp::Background),
|
||||
2 => Some(DisposeOp::Previous),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DisposeOp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match *self {
|
||||
DisposeOp::None => "DISPOSE_OP_NONE",
|
||||
DisposeOp::Background => "DISPOSE_OP_BACKGROUND",
|
||||
DisposeOp::Previous => "DISPOSE_OP_PREVIOUS",
|
||||
};
|
||||
write!(f, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
/// How pixels are written into the buffer.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum BlendOp {
|
||||
/// Pixels overwrite the value at their position.
|
||||
Source = 0,
|
||||
/// The new pixels are blended into the current state based on alpha.
|
||||
Over = 1,
|
||||
}
|
||||
|
||||
impl BlendOp {
|
||||
/// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
|
||||
pub fn from_u8(n: u8) -> Option<BlendOp> {
|
||||
match n {
|
||||
0 => Some(BlendOp::Source),
|
||||
1 => Some(BlendOp::Over),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BlendOp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match *self {
|
||||
BlendOp::Source => "BLEND_OP_SOURCE",
|
||||
BlendOp::Over => "BLEND_OP_OVER",
|
||||
};
|
||||
write!(f, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Frame control information
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct FrameControl {
|
||||
/// Sequence number of the animation chunk, starting from 0
|
||||
pub sequence_number: u32,
|
||||
@ -110,9 +178,36 @@ pub struct FrameControl {
|
||||
/// Frame delay fraction denominator
|
||||
pub delay_den: u16,
|
||||
/// Type of frame area disposal to be done after rendering this frame
|
||||
pub dispose_op: u8,
|
||||
pub dispose_op: DisposeOp,
|
||||
/// Type of frame area rendering for this frame
|
||||
pub blend_op: u8,
|
||||
pub blend_op: BlendOp,
|
||||
}
|
||||
|
||||
impl Default for FrameControl {
|
||||
fn default() -> FrameControl {
|
||||
FrameControl {
|
||||
sequence_number: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
x_offset: 0,
|
||||
y_offset: 0,
|
||||
delay_num: 1,
|
||||
delay_den: 30,
|
||||
dispose_op: DisposeOp::None,
|
||||
blend_op: BlendOp::Source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameControl {
|
||||
pub fn set_seq_num(&mut self, s: u32) {
|
||||
self.sequence_number = s;
|
||||
}
|
||||
|
||||
pub fn inc_seq_num(&mut self, i: u32) {
|
||||
self.sequence_number += i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Animation control information
|
||||
@ -124,6 +219,7 @@ pub struct AnimationControl {
|
||||
pub num_plays: u32,
|
||||
}
|
||||
|
||||
/// The type and strength of applied compression.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Compression {
|
||||
/// Default level
|
||||
@ -140,28 +236,6 @@ pub enum Compression {
|
||||
Rle,
|
||||
}
|
||||
|
||||
impl From<deflate::Compression> for Compression {
|
||||
fn from(c: deflate::Compression) -> Self {
|
||||
match c {
|
||||
deflate::Compression::Default => Compression::Default,
|
||||
deflate::Compression::Fast => Compression::Fast,
|
||||
deflate::Compression::Best => Compression::Best,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Compression> for deflate::CompressionOptions {
|
||||
fn from(c: Compression) -> Self {
|
||||
match c {
|
||||
Compression::Default => deflate::CompressionOptions::default(),
|
||||
Compression::Fast => deflate::CompressionOptions::fast(),
|
||||
Compression::Best => deflate::CompressionOptions::high(),
|
||||
Compression::Huffman => deflate::CompressionOptions::huffman_only(),
|
||||
Compression::Rle => deflate::CompressionOptions::rle(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// PNG info struct
|
||||
#[derive(Debug)]
|
||||
pub struct Info {
|
||||
@ -194,7 +268,7 @@ impl Default for Info {
|
||||
animation_control: None,
|
||||
// Default to `deflate::Compresion::Fast` and `filter::FilterType::Sub`
|
||||
// to maintain backward compatible output.
|
||||
compression: deflate::Compression::Fast.into(),
|
||||
compression: Compression::Fast,
|
||||
filter: filter::FilterType::Sub,
|
||||
}
|
||||
}
|
||||
@ -296,3 +370,35 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[cfg(feature = "png-encoding")]
|
||||
mod deflate_convert {
|
||||
extern crate deflate;
|
||||
use super::Compression;
|
||||
|
||||
impl From<deflate::Compression> for Compression {
|
||||
fn from(c: deflate::Compression) -> Self {
|
||||
match c {
|
||||
deflate::Compression::Default => Compression::Default,
|
||||
deflate::Compression::Fast => Compression::Fast,
|
||||
deflate::Compression::Best => Compression::Best,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Compression> for deflate::CompressionOptions {
|
||||
fn from(c: Compression) -> Self {
|
||||
match c {
|
||||
Compression::Default => deflate::CompressionOptions::default(),
|
||||
Compression::Fast => deflate::CompressionOptions::fast(),
|
||||
Compression::Best => deflate::CompressionOptions::high(),
|
||||
Compression::Huffman => deflate::CompressionOptions::huffman_only(),
|
||||
Compression::Rle => deflate::CompressionOptions::rle(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
88
third_party/rust/png/src/crc.rs
vendored
88
third_party/rust/png/src/crc.rs
vendored
@ -1,88 +0,0 @@
|
||||
|
||||
const CRC_TABLE: [u32; 256] = [
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d
|
||||
];
|
||||
|
||||
/// Crc-32 checksum calculation
|
||||
#[derive(Debug)]
|
||||
pub struct Crc32 {
|
||||
crc: u32,
|
||||
}
|
||||
|
||||
impl Crc32 {
|
||||
/// Create a new hasher.
|
||||
pub fn new() -> Crc32 {
|
||||
Crc32 {crc: 0xFFFFFFFF}
|
||||
}
|
||||
|
||||
/// Resets the hasher.
|
||||
pub fn reset(&mut self) {
|
||||
*self = Self::new()
|
||||
}
|
||||
|
||||
/// Update the internal hasher with the bytes from ```buf```
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
for &byte in buf {
|
||||
let a = (self.crc ^ byte as u32) & 0xFF;
|
||||
let b = self.crc >> 8;
|
||||
|
||||
self.crc = CRC_TABLE[a as usize] ^ b;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the computed hash.
|
||||
pub fn checksum(&self) -> u32 {
|
||||
self.crc ^ 0xFFFFFFFF
|
||||
}
|
||||
}
|
174
third_party/rust/png/src/decoder/mod.rs
vendored
174
third_party/rust/png/src/decoder/mod.rs
vendored
@ -7,11 +7,10 @@ use std::mem;
|
||||
use std::borrow;
|
||||
use std::io::{Read, Write, BufReader, BufRead};
|
||||
|
||||
use traits::{HasParameters, Parameter};
|
||||
use common::{ColorType, BitDepth, Info, Transformations};
|
||||
use filter::{unfilter, FilterType};
|
||||
use chunk::IDAT;
|
||||
use utils;
|
||||
use crate::common::{ColorType, BitDepth, Info, Transformations};
|
||||
use crate::filter::{unfilter, FilterType};
|
||||
use crate::chunk::IDAT;
|
||||
use crate::utils;
|
||||
|
||||
/*
|
||||
pub enum InterlaceHandling {
|
||||
@ -22,22 +21,10 @@ pub enum InterlaceHandling {
|
||||
/// Only fill the needed pixels
|
||||
Sparkle
|
||||
}
|
||||
|
||||
impl Parameter<Reader> for InterlaceHandling {
|
||||
fn set_param(self, this: &mut Reader) {
|
||||
this.color_output = self
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
impl<R: Read> Parameter<Decoder<R>> for Transformations {
|
||||
fn set_param(self, this: &mut Decoder<R>) {
|
||||
this.transform = self
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/// Output info
|
||||
#[derive(Debug)]
|
||||
pub struct OutputInfo {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
@ -54,15 +41,16 @@ impl OutputInfo {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
/// Limits on the resources the `Decoder` is allowed too use
|
||||
pub struct Limits {
|
||||
/// max number of pixels: `width * height` (default: 67M = 2<sup>26</sup>)
|
||||
pub pixels: u64,
|
||||
/// maximum number of bytes the decoder is allowed to allocate, default is 64Mib
|
||||
pub bytes: usize,
|
||||
}
|
||||
|
||||
impl Default for Limits {
|
||||
fn default() -> Limits {
|
||||
Limits {
|
||||
pixels: 1 << 26,
|
||||
bytes: 1024*1024*64,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,7 +61,7 @@ pub struct Decoder<R: Read> {
|
||||
r: R,
|
||||
/// Output transformations
|
||||
transform: Transformations,
|
||||
/// Images that are considered too big
|
||||
/// Limits on resources the Decoder is allowed to use
|
||||
limits: Limits,
|
||||
}
|
||||
|
||||
@ -85,24 +73,24 @@ impl<R: Read> Decoder<R> {
|
||||
pub fn new_with_limits(r: R, l: Limits) -> Decoder<R> {
|
||||
Decoder {
|
||||
r: r,
|
||||
transform: ::Transformations::EXPAND | ::Transformations::SCALE_16 | ::Transformations::STRIP_16,
|
||||
transform: crate::Transformations::EXPAND | crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16,
|
||||
limits: l,
|
||||
}
|
||||
}
|
||||
|
||||
/// Images that are considered too big
|
||||
/// Limit resource usage
|
||||
///
|
||||
/// ```
|
||||
/// use std::fs::File;
|
||||
/// use png::{Decoder, Limits};
|
||||
/// // This image is 32x32 pixels, so it's more than four pixels in size.
|
||||
/// // This image is 32x32 pixels, so the deocder will allocate more than four bytes
|
||||
/// let mut limits = Limits::default();
|
||||
/// limits.pixels = 4;
|
||||
/// limits.bytes = 4;
|
||||
/// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
|
||||
/// assert!(decoder.read_info().is_err());
|
||||
/// // This image is 32x32 pixels, so it's exactly 1024 pixels in size.
|
||||
/// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
|
||||
/// let mut limits = Limits::default();
|
||||
/// limits.pixels = 1024;
|
||||
/// limits.bytes = 10*1024;
|
||||
/// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
|
||||
/// assert!(decoder.read_info().is_ok());
|
||||
/// ```
|
||||
@ -112,8 +100,8 @@ impl<R: Read> Decoder<R> {
|
||||
|
||||
/// Reads all meta data until the first IDAT chunk
|
||||
pub fn read_info(self) -> Result<(OutputInfo, Reader<R>), DecodingError> {
|
||||
let mut r = Reader::new(self.r, StreamingDecoder::new(), self.transform);
|
||||
try!(r.init());
|
||||
let mut r = Reader::new(self.r, StreamingDecoder::new(), self.transform, self.limits);
|
||||
r.init()?;
|
||||
let (ct, bits) = r.output_color_type();
|
||||
let info = {
|
||||
let info = r.info();
|
||||
@ -125,17 +113,17 @@ impl<R: Read> Decoder<R> {
|
||||
line_size: r.output_line_size(info.width),
|
||||
}
|
||||
};
|
||||
let (width, height, pixels) = (info.width as u64, info.height as u64, self.limits.pixels);
|
||||
if width.checked_mul(height).map(|p| p > pixels).unwrap_or(true) {
|
||||
// DecodingError::Other is used for backwards compatibility.
|
||||
// In the next major version, add a variant for this.
|
||||
return Err(DecodingError::Other(borrow::Cow::Borrowed("pixels limit exceeded")));
|
||||
}
|
||||
Ok((info, r))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> HasParameters for Decoder<R> {}
|
||||
/// Set the allowed and performed transformations.
|
||||
///
|
||||
/// A transformation is a pre-processing on the raw image data modifying content or encoding.
|
||||
/// Many options have an impact on memory or CPU usage during decoding.
|
||||
pub fn set_transformations(&mut self, transform: Transformations) {
|
||||
self.transform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
struct ReadDecoder<R: Read> {
|
||||
reader: BufReader<R>,
|
||||
@ -149,13 +137,13 @@ impl<R: Read> ReadDecoder<R> {
|
||||
fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError> {
|
||||
while !self.at_eof {
|
||||
let (consumed, result) = {
|
||||
let buf = try!(self.reader.fill_buf());
|
||||
let buf = self.reader.fill_buf()?;
|
||||
if buf.is_empty() {
|
||||
return Err(DecodingError::Format(
|
||||
"unexpected EOF".into()
|
||||
))
|
||||
}
|
||||
try!(self.decoder.update(buf, image_data))
|
||||
self.decoder.update(buf, image_data)?
|
||||
};
|
||||
self.reader.consume(consumed);
|
||||
match result {
|
||||
@ -187,7 +175,8 @@ pub struct Reader<R: Read> {
|
||||
/// Output transformations
|
||||
transform: Transformations,
|
||||
/// Processed line
|
||||
processed: Vec<u8>
|
||||
processed: Vec<u8>,
|
||||
limits: Limits,
|
||||
}
|
||||
|
||||
macro_rules! get_info(
|
||||
@ -198,7 +187,7 @@ macro_rules! get_info(
|
||||
|
||||
impl<R: Read> Reader<R> {
|
||||
/// Creates a new PNG reader
|
||||
fn new(r: R, d: StreamingDecoder, t: Transformations) -> Reader<R> {
|
||||
fn new(r: R, d: StreamingDecoder, t: Transformations, limits: Limits) -> Reader<R> {
|
||||
Reader {
|
||||
decoder: ReadDecoder {
|
||||
reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r),
|
||||
@ -211,18 +200,19 @@ impl<R: Read> Reader<R> {
|
||||
prev: Vec::new(),
|
||||
current: Vec::new(),
|
||||
transform: t,
|
||||
processed: Vec::new()
|
||||
processed: Vec::new(),
|
||||
limits,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads all meta data until the first IDAT chunk
|
||||
fn init(&mut self) -> Result<(), DecodingError> {
|
||||
use Decoded::*;
|
||||
use crate::Decoded::*;
|
||||
if self.decoder.info().is_some() {
|
||||
Ok(())
|
||||
} else {
|
||||
loop {
|
||||
match try!(self.decoder.decode_next(&mut Vec::new())) {
|
||||
match self.decoder.decode_next(&mut Vec::new())? {
|
||||
Some(ChunkBegin(_, IDAT)) => break,
|
||||
None => return Err(DecodingError::Format(
|
||||
"IDAT chunk missing".into()
|
||||
@ -243,7 +233,7 @@ impl<R: Read> Reader<R> {
|
||||
self.adam7 = Some(utils::Adam7Iterator::new(info.width, info.height))
|
||||
}
|
||||
}
|
||||
self.allocate_out_buf();
|
||||
self.allocate_out_buf()?;
|
||||
self.prev = vec![0; self.rowlen];
|
||||
Ok(())
|
||||
}
|
||||
@ -256,7 +246,7 @@ impl<R: Read> Reader<R> {
|
||||
/// Decodes the next frame into `buf`
|
||||
pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
|
||||
// TODO 16 bit
|
||||
let (color_type, _) = self.output_color_type();
|
||||
let (color_type, bit_depth) = self.output_color_type();
|
||||
let width = get_info!(self).width;
|
||||
if buf.len() < self.output_buffer_size() {
|
||||
return Err(DecodingError::Other(
|
||||
@ -264,15 +254,15 @@ impl<R: Read> Reader<R> {
|
||||
))
|
||||
}
|
||||
if get_info!(self).interlaced {
|
||||
while let Some((row, adam7)) = try!(self.next_interlaced_row()) {
|
||||
while let Some((row, adam7)) = self.next_interlaced_row()? {
|
||||
let (pass, line, _) = adam7.unwrap();
|
||||
let bytes = color_type.samples() as u8;
|
||||
utils::expand_pass(buf, width * bytes as u32, row, pass, line, bytes);
|
||||
let samples = color_type.samples() as u8;
|
||||
utils::expand_pass(buf, width, row, pass, line, samples * (bit_depth as u8));
|
||||
}
|
||||
} else {
|
||||
let mut len = 0;
|
||||
while let Some(row) = try!(self.next_row()) {
|
||||
len += try!((&mut buf[len..]).write(row));
|
||||
while let Some(row) = self.next_row()? {
|
||||
len += (&mut buf[len..]).write(row)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -285,15 +275,15 @@ impl<R: Read> Reader<R> {
|
||||
|
||||
/// Returns the next processed row of the image
|
||||
pub fn next_interlaced_row(&mut self) -> Result<Option<(&[u8], Option<(u8, u32, u32)>)>, DecodingError> {
|
||||
use common::ColorType::*;
|
||||
use crate::common::ColorType::*;
|
||||
let transform = self.transform;
|
||||
if transform == ::Transformations::IDENTITY {
|
||||
if transform == crate::Transformations::IDENTITY {
|
||||
self.next_raw_interlaced_row()
|
||||
} else {
|
||||
// swap buffer to circumvent borrow issues
|
||||
let mut buffer = mem::replace(&mut self.processed, Vec::new());
|
||||
let (got_next, adam7) = if let Some((row, adam7)) = try!(self.next_raw_interlaced_row()) {
|
||||
try!((&mut buffer[..]).write(row));
|
||||
let (got_next, adam7) = if let Some((row, adam7)) = self.next_raw_interlaced_row()? {
|
||||
(&mut buffer[..]).write(row)?;
|
||||
(true, adam7)
|
||||
} else {
|
||||
(false, None)
|
||||
@ -312,7 +302,7 @@ impl<R: Read> Reader<R> {
|
||||
&mut *self.processed
|
||||
};
|
||||
let mut len = output_buffer.len();
|
||||
if transform.contains(::Transformations::EXPAND) {
|
||||
if transform.contains(crate::Transformations::EXPAND) {
|
||||
match color_type {
|
||||
Indexed => {
|
||||
expand_paletted(output_buffer, get_info!(self))?
|
||||
@ -332,7 +322,7 @@ impl<R: Read> Reader<R> {
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
if bit_depth == 16 && transform.intersects(::Transformations::SCALE_16 | ::Transformations::STRIP_16) {
|
||||
if bit_depth == 16 && transform.intersects(crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16) {
|
||||
len /= 2;
|
||||
for i in 0..len {
|
||||
output_buffer[i] = output_buffer[2 * i];
|
||||
@ -351,20 +341,20 @@ impl<R: Read> Reader<R> {
|
||||
/// Returns the color type and the number of bits per sample
|
||||
/// of the data returned by `Reader::next_row` and Reader::frames`.
|
||||
pub fn output_color_type(&mut self) -> (ColorType, BitDepth) {
|
||||
use common::ColorType::*;
|
||||
use crate::common::ColorType::*;
|
||||
let t = self.transform;
|
||||
let info = get_info!(self);
|
||||
if t == ::Transformations::IDENTITY {
|
||||
if t == crate::Transformations::IDENTITY {
|
||||
(info.color_type, info.bit_depth)
|
||||
} else {
|
||||
let bits = match info.bit_depth as u8 {
|
||||
16 if t.intersects(
|
||||
::Transformations::SCALE_16 | ::Transformations::STRIP_16
|
||||
crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16
|
||||
) => 8,
|
||||
_ if t.contains(::Transformations::EXPAND) => 8,
|
||||
_ if t.contains(crate::Transformations::EXPAND) => 8,
|
||||
n => n
|
||||
};
|
||||
let color_type = if t.contains(::Transformations::EXPAND) {
|
||||
let color_type = if t.contains(crate::Transformations::EXPAND) {
|
||||
let has_trns = info.trns.is_some();
|
||||
match info.color_type {
|
||||
Grayscale if has_trns => GrayscaleAlpha,
|
||||
@ -392,7 +382,7 @@ impl<R: Read> Reader<R> {
|
||||
pub fn output_line_size(&self, width: u32) -> usize {
|
||||
let size = self.line_size(width);
|
||||
if get_info!(self).bit_depth as u8 == 16 && self.transform.intersects(
|
||||
::Transformations::SCALE_16 | ::Transformations::STRIP_16
|
||||
crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16
|
||||
) {
|
||||
size / 2
|
||||
} else {
|
||||
@ -402,18 +392,18 @@ impl<R: Read> Reader<R> {
|
||||
|
||||
/// Returns the number of bytes required to decode a deinterlaced row.
|
||||
fn line_size(&self, width: u32) -> usize {
|
||||
use common::ColorType::*;
|
||||
use crate::common::ColorType::*;
|
||||
let t = self.transform;
|
||||
let info = get_info!(self);
|
||||
let trns = info.trns.is_some();
|
||||
// TODO 16 bit
|
||||
let bits = match info.color_type {
|
||||
Indexed if trns && t.contains(::Transformations::EXPAND) => 4 * 8,
|
||||
Indexed if t.contains(::Transformations::EXPAND) => 3 * 8,
|
||||
RGB if trns && t.contains(::Transformations::EXPAND) => 4 * 8,
|
||||
Grayscale if trns && t.contains(::Transformations::EXPAND) => 2 * 8,
|
||||
Grayscale if t.contains(::Transformations::EXPAND) => 1 * 8,
|
||||
GrayscaleAlpha if t.contains(::Transformations::EXPAND) => 2 * 8,
|
||||
Indexed if trns && t.contains(crate::Transformations::EXPAND) => 4 * 8,
|
||||
Indexed if t.contains(crate::Transformations::EXPAND) => 3 * 8,
|
||||
RGB if trns && t.contains(crate::Transformations::EXPAND) => 4 * 8,
|
||||
Grayscale if trns && t.contains(crate::Transformations::EXPAND) => 2 * 8,
|
||||
Grayscale if t.contains(crate::Transformations::EXPAND) => 1 * 8,
|
||||
GrayscaleAlpha if t.contains(crate::Transformations::EXPAND) => 2 * 8,
|
||||
// divide by 2 as it will get mutiplied by two later
|
||||
_ if info.bit_depth as u8 == 16 => info.bits_per_pixel() / 2,
|
||||
_ => info.bits_per_pixel()
|
||||
@ -425,9 +415,14 @@ impl<R: Read> Reader<R> {
|
||||
len + match extra { 0 => 0, _ => 1 }
|
||||
}
|
||||
|
||||
fn allocate_out_buf(&mut self) {
|
||||
fn allocate_out_buf(&mut self) -> Result<(), DecodingError> {
|
||||
let width = get_info!(self).width;
|
||||
self.processed = vec![0; self.line_size(width)]
|
||||
let bytes = self.limits.bytes;
|
||||
if bytes < self.line_size(width) {
|
||||
return Err(DecodingError::LimitsExceeded);
|
||||
}
|
||||
self.processed = vec![0; self.line_size(width)];
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the next raw row of the image
|
||||
@ -473,7 +468,7 @@ impl<R: Read> Reader<R> {
|
||||
))
|
||||
}
|
||||
} else {
|
||||
let val = try!(self.decoder.decode_next(&mut self.current));
|
||||
let val = self.decoder.decode_next(&mut self.current)?;
|
||||
match val {
|
||||
Some(Decoded::ImageData) => {}
|
||||
None => {
|
||||
@ -546,32 +541,3 @@ fn expand_gray_u8(buffer: &mut [u8], info: &Info) {
|
||||
})
|
||||
}
|
||||
}
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate test;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use super::Decoder;
|
||||
use HasParameters;
|
||||
|
||||
#[bench]
|
||||
fn bench_big(b: &mut test::Bencher) {
|
||||
let mut data = Vec::new();
|
||||
File::open("tests/pngsuite/PngSuite.png").unwrap().read_to_end(&mut data).unwrap();
|
||||
let mut decoder = Decoder::new(&*data);
|
||||
decoder.set(::Transformations::IDENTITY);
|
||||
let (info, _) = decoder.read_info().unwrap();
|
||||
let mut image = vec![0; info.buffer_size()];
|
||||
b.iter(|| {
|
||||
let mut decoder = Decoder::new(&*data);
|
||||
decoder.set(::Transformations::IDENTITY);
|
||||
let (_, mut decoder) = decoder.read_info().unwrap();
|
||||
test::black_box(decoder.next_frame(&mut image)).unwrap();
|
||||
});
|
||||
b.bytes = info.buffer_size() as u64
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
103
third_party/rust/png/src/decoder/stream.rs
vendored
103
third_party/rust/png/src/decoder/stream.rs
vendored
@ -1,3 +1,6 @@
|
||||
extern crate crc32fast;
|
||||
extern crate inflate;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::default::Default;
|
||||
use std::error;
|
||||
@ -6,17 +9,30 @@ use std::io;
|
||||
use std::cmp::min;
|
||||
use std::convert::From;
|
||||
|
||||
extern crate inflate;
|
||||
use crc32fast::Hasher as Crc32;
|
||||
|
||||
use self::inflate::InflateStream;
|
||||
use crc::Crc32;
|
||||
use traits::ReadBytesExt;
|
||||
use common::{ColorType, BitDepth, Info, Unit, PixelDimensions, AnimationControl, FrameControl};
|
||||
use chunk::{self, ChunkType, IHDR, IDAT, IEND};
|
||||
use crate::traits::ReadBytesExt;
|
||||
use crate::common::{BitDepth, BlendOp, ColorType, DisposeOp, Info, Unit, PixelDimensions, AnimationControl, FrameControl};
|
||||
use crate::chunk::{self, ChunkType, IHDR, IDAT, IEND};
|
||||
|
||||
/// TODO check if these size are reasonable
|
||||
pub const CHUNCK_BUFFER_SIZE: usize = 32*1024;
|
||||
|
||||
/// Determines if checksum checks should be disabled globally.
|
||||
///
|
||||
/// This is used only in fuzzing. `afl` automatically adds `--cfg fuzzing` to RUSTFLAGS which can
|
||||
/// be used to detect that build.
|
||||
const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
|
||||
|
||||
fn zlib_stream() -> InflateStream {
|
||||
if CHECKSUM_DISABLED {
|
||||
InflateStream::from_zlib_no_checksum()
|
||||
} else {
|
||||
InflateStream::from_zlib()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum U32Value {
|
||||
// CHUNKS
|
||||
@ -69,7 +85,8 @@ pub enum DecodingError {
|
||||
chunk: ChunkType
|
||||
},
|
||||
Other(Cow<'static, str>),
|
||||
CorruptFlateStream
|
||||
CorruptFlateStream,
|
||||
LimitsExceeded,
|
||||
}
|
||||
|
||||
impl error::Error for DecodingError {
|
||||
@ -80,14 +97,15 @@ impl error::Error for DecodingError {
|
||||
Format(ref desc) | Other(ref desc) => &desc,
|
||||
InvalidSignature => "invalid signature",
|
||||
CrcMismatch { .. } => "CRC error",
|
||||
CorruptFlateStream => "compressed data stream corrupted"
|
||||
CorruptFlateStream => "compressed data stream corrupted",
|
||||
LimitsExceeded => "limits are exceeded"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DecodingError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "{}", (self as &error::Error).description())
|
||||
write!(fmt, "{}", (self as &dyn error::Error).description())
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +152,7 @@ impl StreamingDecoder {
|
||||
StreamingDecoder {
|
||||
state: Some(State::Signature(0, [0; 7])),
|
||||
current_chunk: (Crc32::new(), 0, Vec::with_capacity(CHUNCK_BUFFER_SIZE)),
|
||||
inflater: if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()},
|
||||
inflater: zlib_stream(),
|
||||
info: None,
|
||||
current_seq_no: None,
|
||||
have_idat: false
|
||||
@ -147,7 +165,7 @@ impl StreamingDecoder {
|
||||
self.current_chunk.0 = Crc32::new();
|
||||
self.current_chunk.1 = 0;
|
||||
self.current_chunk.2.clear();
|
||||
self.inflater = if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()};
|
||||
self.inflater = zlib_stream();
|
||||
self.info = None;
|
||||
self.current_seq_no = None;
|
||||
self.have_idat = false;
|
||||
@ -237,7 +255,8 @@ impl StreamingDecoder {
|
||||
)
|
||||
},
|
||||
Crc(type_str) => {
|
||||
if cfg!(fuzzing) || val == self.current_chunk.0.checksum() {
|
||||
let sum = self.current_chunk.0.clone().finalize();
|
||||
if CHECKSUM_DISABLED || val == sum {
|
||||
goto!(
|
||||
State::U32(U32Value::Length),
|
||||
emit if type_str == IEND {
|
||||
@ -250,7 +269,7 @@ impl StreamingDecoder {
|
||||
Err(DecodingError::CrcMismatch {
|
||||
recover: 1,
|
||||
crc_val: val,
|
||||
crc_sum: self.current_chunk.0.checksum(),
|
||||
crc_sum: sum,
|
||||
chunk: type_str
|
||||
})
|
||||
}
|
||||
@ -279,7 +298,7 @@ impl StreamingDecoder {
|
||||
chunk::fdAT => {
|
||||
if let Some(seq_no) = self.current_seq_no {
|
||||
let mut buf = &self.current_chunk.2[..];
|
||||
let next_seq_no = try!(buf.read_be());
|
||||
let next_seq_no = buf.read_be()?;
|
||||
if next_seq_no != seq_no + 1 {
|
||||
return Err(DecodingError::Format(format!(
|
||||
"Sequence is not in order, expected #{} got #{}.",
|
||||
@ -300,7 +319,7 @@ impl StreamingDecoder {
|
||||
// Handle other chunks
|
||||
_ => {
|
||||
if self.current_chunk.1 == 0 { // complete chunk
|
||||
Ok((0, try!(self.parse_chunk(type_str))))
|
||||
Ok((0, self.parse_chunk(type_str)?))
|
||||
} else {
|
||||
goto!(
|
||||
0, ReadChunk(type_str, true),
|
||||
@ -341,7 +360,7 @@ impl StreamingDecoder {
|
||||
}
|
||||
DecodeData(type_str, mut n) => {
|
||||
let chunk_len = self.current_chunk.2.len();
|
||||
let (c, data) = try!(self.inflater.update(&self.current_chunk.2[n..]));
|
||||
let (c, data) = self.inflater.update(&self.current_chunk.2[n..])?;
|
||||
image_data.extend_from_slice(data);
|
||||
n += c;
|
||||
if n == chunk_len && data.len() == 0 && c == 0 {
|
||||
@ -408,7 +427,7 @@ impl StreamingDecoder {
|
||||
fn parse_fctl(&mut self)
|
||||
-> Result<Decoded, DecodingError> {
|
||||
let mut buf = &self.current_chunk.2[..];
|
||||
let next_seq_no = try!(buf.read_be());
|
||||
let next_seq_no = buf.read_be()?;
|
||||
|
||||
// Asuming that fcTL is required before *every* fdAT-sequence
|
||||
self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
|
||||
@ -430,17 +449,23 @@ impl StreamingDecoder {
|
||||
}
|
||||
0
|
||||
});
|
||||
self.inflater = if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()};
|
||||
self.inflater = zlib_stream();
|
||||
let fc = FrameControl {
|
||||
sequence_number: next_seq_no,
|
||||
width: try!(buf.read_be()),
|
||||
height: try!(buf.read_be()),
|
||||
x_offset: try!(buf.read_be()),
|
||||
y_offset: try!(buf.read_be()),
|
||||
delay_num: try!(buf.read_be()),
|
||||
delay_den: try!(buf.read_be()),
|
||||
dispose_op: try!(buf.read_be()),
|
||||
blend_op : try!(buf.read_be()),
|
||||
width: buf.read_be()?,
|
||||
height: buf.read_be()?,
|
||||
x_offset: buf.read_be()?,
|
||||
y_offset: buf.read_be()?,
|
||||
delay_num: buf.read_be()?,
|
||||
delay_den: buf.read_be()?,
|
||||
dispose_op: match DisposeOp::from_u8(buf.read_be()?) {
|
||||
Some(dispose_op) => dispose_op,
|
||||
None => return Err(DecodingError::Format("invalid dispose operation".into()))
|
||||
},
|
||||
blend_op : match BlendOp::from_u8(buf.read_be()?) {
|
||||
Some(blend_op) => blend_op,
|
||||
None => return Err(DecodingError::Format("invalid blend operation".into()))
|
||||
},
|
||||
};
|
||||
self.info.as_mut().unwrap().frame_control = Some(fc.clone());
|
||||
Ok(Decoded::FrameControl(fc))
|
||||
@ -455,8 +480,8 @@ impl StreamingDecoder {
|
||||
} else {
|
||||
let mut buf = &self.current_chunk.2[..];
|
||||
let actl = AnimationControl {
|
||||
num_frames: try!(buf.read_be()),
|
||||
num_plays: try!(buf.read_be())
|
||||
num_frames: buf.read_be()?,
|
||||
num_plays: buf.read_be()?
|
||||
};
|
||||
self.info.as_mut().unwrap().animation_control = Some(actl);
|
||||
Ok(Decoded::AnimationControl(actl))
|
||||
@ -475,9 +500,9 @@ impl StreamingDecoder {
|
||||
|
||||
fn parse_trns(&mut self)
|
||||
-> Result<Decoded, DecodingError> {
|
||||
use common::ColorType::*;
|
||||
use crate::common::ColorType::*;
|
||||
let (color_type, bit_depth) = {
|
||||
let info = try!(self.get_info_or_err());
|
||||
let info = self.get_info_or_err()?;
|
||||
(info.color_type, info.bit_depth as u8)
|
||||
};
|
||||
let mut vec = Vec::new();
|
||||
@ -539,9 +564,9 @@ impl StreamingDecoder {
|
||||
))
|
||||
} else {
|
||||
let mut buf = &self.current_chunk.2[..];
|
||||
let xppu = try!(buf.read_be());
|
||||
let yppu = try!(buf.read_be());
|
||||
let unit = try!(buf.read_be());
|
||||
let xppu = buf.read_be()?;
|
||||
let yppu = buf.read_be()?;
|
||||
let unit = buf.read_be()?;
|
||||
let unit = match Unit::from_u8(unit) {
|
||||
Some(unit) => unit,
|
||||
None => return Err(DecodingError::Format(
|
||||
@ -562,35 +587,35 @@ impl StreamingDecoder {
|
||||
-> Result<Decoded, DecodingError> {
|
||||
// TODO: check if color/bit depths combination is valid
|
||||
let mut buf = &self.current_chunk.2[..];
|
||||
let width = try!(buf.read_be());
|
||||
let height = try!(buf.read_be());
|
||||
let bit_depth = try!(buf.read_be());
|
||||
let width = buf.read_be()?;
|
||||
let height = buf.read_be()?;
|
||||
let bit_depth = buf.read_be()?;
|
||||
let bit_depth = match BitDepth::from_u8(bit_depth) {
|
||||
Some(bits) => bits,
|
||||
None => return Err(DecodingError::Format(
|
||||
format!("invalid bit depth ({})", bit_depth).into()
|
||||
))
|
||||
};
|
||||
let color_type = try!(buf.read_be());
|
||||
let color_type = buf.read_be()?;
|
||||
let color_type = match ColorType::from_u8(color_type) {
|
||||
Some(color_type) => color_type,
|
||||
None => return Err(DecodingError::Format(
|
||||
format!("invalid color type ({})", color_type).into()
|
||||
))
|
||||
};
|
||||
match try!(buf.read_be()) { // compression method
|
||||
match buf.read_be()? { // compression method
|
||||
0u8 => (),
|
||||
n => return Err(DecodingError::Format(
|
||||
format!("unknown compression method ({})", n).into()
|
||||
))
|
||||
}
|
||||
match try!(buf.read_be()) { // filter method
|
||||
match buf.read_be()? { // filter method
|
||||
0u8 => (),
|
||||
n => return Err(DecodingError::Format(
|
||||
format!("unknown filter method ({})", n).into()
|
||||
))
|
||||
}
|
||||
let interlaced = match try!(buf.read_be()) {
|
||||
let interlaced = match buf.read_be()? {
|
||||
0u8 => false,
|
||||
1 => {
|
||||
true
|
||||
|
280
third_party/rust/png/src/encoder.rs
vendored
280
third_party/rust/png/src/encoder.rs
vendored
@ -1,17 +1,19 @@
|
||||
extern crate crc32fast;
|
||||
extern crate deflate;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io::{self, Write};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::mem;
|
||||
use std::result;
|
||||
|
||||
use chunk;
|
||||
use crc::Crc32;
|
||||
use common::{Info, ColorType, BitDepth, Compression};
|
||||
use filter::{FilterType, filter};
|
||||
use traits::{WriteBytesExt, HasParameters, Parameter};
|
||||
use crc32fast::Hasher as Crc32;
|
||||
|
||||
use crate::chunk;
|
||||
use crate::common::{Info, ColorType, BitDepth, Compression};
|
||||
use crate::filter::{FilterType, filter};
|
||||
use crate::traits::WriteBytesExt;
|
||||
|
||||
pub type Result<T> = result::Result<T, EncodingError>;
|
||||
|
||||
@ -33,7 +35,7 @@ impl error::Error for EncodingError {
|
||||
|
||||
impl fmt::Display for EncodingError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
|
||||
write!(fmt, "{}", (self as &error::Error).description())
|
||||
write!(fmt, "{}", (self as &dyn error::Error).description())
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +46,7 @@ impl From<io::Error> for EncodingError {
|
||||
}
|
||||
impl From<EncodingError> for io::Error {
|
||||
fn from(err: EncodingError) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, (&err as &error::Error).description())
|
||||
io::Error::new(io::ErrorKind::Other, (&err as &dyn error::Error).description())
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,34 +67,39 @@ impl<W: Write> Encoder<W> {
|
||||
pub fn write_header(self) -> Result<Writer<W>> {
|
||||
Writer::new(self.w, self.info).init()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> HasParameters for Encoder<W> {}
|
||||
|
||||
impl<W: Write> Parameter<Encoder<W>> for ColorType {
|
||||
fn set_param(self, this: &mut Encoder<W>) {
|
||||
this.info.color_type = self
|
||||
/// Set the color of the encoded image.
|
||||
///
|
||||
/// These correspond to the color types in the png IHDR data that will be written. The length
|
||||
/// of the image data that is later supplied must match the color type, otherwise an error will
|
||||
/// be emitted.
|
||||
pub fn set_color(&mut self, color: ColorType) {
|
||||
self.info.color_type = color;
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Parameter<Encoder<W>> for BitDepth {
|
||||
fn set_param(self, this: &mut Encoder<W>) {
|
||||
this.info.bit_depth = self
|
||||
/// Set the indicated depth of the image data.
|
||||
pub fn set_depth(&mut self, depth: BitDepth) {
|
||||
self.info.bit_depth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set compression param for a ```Compression``` or any type that can transform
|
||||
/// into a ```Compression```, notably ```deflate::Compression``` and
|
||||
/// ```deflate::CompressionOptions``` which "just work".
|
||||
impl<W: Write, C: Into<Compression>> Parameter<Encoder<W>> for C {
|
||||
fn set_param(self, this: &mut Encoder<W>) {
|
||||
this.info.compression = self.into()
|
||||
/// Set compression parameters.
|
||||
///
|
||||
/// Accepts a `Compression` or any type that can transform into a `Compression`. Notably `deflate::Compression` and
|
||||
/// `deflate::CompressionOptions` which "just work".
|
||||
pub fn set_compression<C: Into<Compression>>(&mut self, compression: C) {
|
||||
self.info.compression = compression.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl <W: Write> Parameter<Encoder<W>> for FilterType {
|
||||
fn set_param(self, this: &mut Encoder<W>) {
|
||||
this.info.filter = self
|
||||
/// 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`].
|
||||
///
|
||||
/// [`FilterType::Sub`]: enum.FilterType.html#variant.Sub
|
||||
/// [`FilterType::Paeth`]: enum.FilterType.html#variant.Paeth
|
||||
pub fn set_filter(&mut self, filter: FilterType) {
|
||||
self.info.filter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,25 +116,25 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
|
||||
fn init(mut self) -> Result<Self> {
|
||||
try!(self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10]));
|
||||
self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?;
|
||||
let mut data = [0; 13];
|
||||
try!((&mut data[..]).write_be(self.info.width));
|
||||
try!((&mut data[4..]).write_be(self.info.height));
|
||||
(&mut data[..]).write_be(self.info.width)?;
|
||||
(&mut data[4..]).write_be(self.info.height)?;
|
||||
data[8] = self.info.bit_depth as u8;
|
||||
data[9] = self.info.color_type as u8;
|
||||
data[12] = if self.info.interlaced { 1 } else { 0 };
|
||||
try!(self.write_chunk(chunk::IHDR, &data));
|
||||
self.write_chunk(chunk::IHDR, &data)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn write_chunk(&mut self, name: [u8; 4], data: &[u8]) -> Result<()> {
|
||||
try!(self.w.write_be(data.len() as u32));
|
||||
try!(self.w.write_all(&name));
|
||||
try!(self.w.write_all(data));
|
||||
self.w.write_be(data.len() as u32)?;
|
||||
self.w.write_all(&name)?;
|
||||
self.w.write_all(data)?;
|
||||
let mut crc = Crc32::new();
|
||||
crc.update(&name);
|
||||
crc.update(data);
|
||||
try!(self.w.write_be(crc.checksum()));
|
||||
self.w.write_be(crc.finalize())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -146,12 +153,29 @@ impl<W: Write> Writer<W> {
|
||||
let filter_method = self.info.filter;
|
||||
for line in data.chunks(in_len) {
|
||||
current.copy_from_slice(&line);
|
||||
try!(zlib.write_all(&[filter_method as u8]));
|
||||
zlib.write_all(&[filter_method as u8])?;
|
||||
filter(filter_method, bpp, &prev, &mut current);
|
||||
try!(zlib.write_all(¤t));
|
||||
zlib.write_all(¤t)?;
|
||||
mem::swap(&mut prev, &mut current);
|
||||
}
|
||||
self.write_chunk(chunk::IDAT, &try!(zlib.finish()))
|
||||
self.write_chunk(chunk::IDAT, &zlib.finish()?)
|
||||
}
|
||||
|
||||
/// Create an stream writer.
|
||||
///
|
||||
/// This allows you create images that do not fit
|
||||
/// in memory. The default chunk size is 4K, use
|
||||
/// `stream_writer_with_size` to set another chuck
|
||||
/// size.
|
||||
pub fn stream_writer(&mut self) -> StreamWriter<W> {
|
||||
self.stream_writer_with_size(4 * 1024)
|
||||
}
|
||||
|
||||
/// Create a stream writer with custom buffer size.
|
||||
///
|
||||
/// See `stream_writer`
|
||||
pub fn stream_writer_with_size(&mut self, size: usize) -> StreamWriter<W> {
|
||||
StreamWriter::new(self, size)
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +185,125 @@ impl<W: Write> Drop for Writer<W> {
|
||||
}
|
||||
}
|
||||
|
||||
struct ChunkWriter<'a, W: Write> {
|
||||
writer: &'a mut Writer<W>,
|
||||
buffer: Vec<u8>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> ChunkWriter<'a, W> {
|
||||
fn new(writer: &'a mut Writer<W>, buf_len: usize) -> ChunkWriter<'a, W> {
|
||||
ChunkWriter {
|
||||
writer,
|
||||
buffer: vec![0; buf_len],
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Write for ChunkWriter<'a, W> {
|
||||
fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
|
||||
let written = buf.read(&mut self.buffer[self.index..])?;
|
||||
self.index += written;
|
||||
|
||||
if self.index + 1 >= self.buffer.len() {
|
||||
self.writer.write_chunk(chunk::IDAT, &self.buffer)?;
|
||||
self.index = 0;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
if self.index > 0 {
|
||||
self.writer.write_chunk(chunk::IDAT, &self.buffer[..self.index+1])?;
|
||||
}
|
||||
self.index = 0;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Drop for ChunkWriter<'a, W> {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Streaming png writer
|
||||
///
|
||||
/// This may may silently fail in the destructor so it is a good idea to call
|
||||
/// `finish` or `flush` before droping.
|
||||
pub struct StreamWriter<'a, W: Write> {
|
||||
writer: deflate::write::ZlibEncoder<ChunkWriter<'a, W>>,
|
||||
prev_buf: Vec<u8>,
|
||||
curr_buf: Vec<u8>,
|
||||
index: usize,
|
||||
bpp: usize,
|
||||
filter: FilterType,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> StreamWriter<'a, W> {
|
||||
fn new(writer: &'a mut Writer<W>, buf_len: usize) -> StreamWriter<'a, W> {
|
||||
let bpp = writer.info.bytes_per_pixel();
|
||||
let in_len = writer.info.raw_row_length() - 1;
|
||||
let filter = writer.info.filter;
|
||||
let prev_buf = vec![0; in_len];
|
||||
let curr_buf = vec![0; in_len];
|
||||
|
||||
let compression = writer.info.compression.clone();
|
||||
let chunk_writer = ChunkWriter::new(writer, buf_len);
|
||||
let zlib = deflate::write::ZlibEncoder::new(chunk_writer, compression);
|
||||
|
||||
StreamWriter {
|
||||
writer: zlib,
|
||||
index: 0,
|
||||
prev_buf,
|
||||
curr_buf,
|
||||
bpp,
|
||||
filter,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(mut self) -> Result<()> {
|
||||
// TODO: call `writer.finish` somehow?
|
||||
self.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Write for StreamWriter<'a, W> {
|
||||
fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
|
||||
let written = buf.read(&mut self.curr_buf[self.index..])?;
|
||||
self.index += written;
|
||||
|
||||
if self.index >= self.curr_buf.len() {
|
||||
self.writer.write_all(&[self.filter as u8])?;
|
||||
filter(self.filter, self.bpp, &self.prev_buf, &mut self.curr_buf);
|
||||
self.writer.write_all(&self.curr_buf)?;
|
||||
mem::swap(&mut self.prev_buf, &mut self.curr_buf);
|
||||
self.index = 0;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.writer.flush()?;
|
||||
if self.index > 0 {
|
||||
let message = format!("wrong data size, got {} bytes too many", self.index);
|
||||
return Err(EncodingError::Format(message.into()).into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Drop for StreamWriter<'a, W> {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.flush();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -183,7 +326,7 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
// Decode image
|
||||
let decoder = ::Decoder::new(File::open(path).unwrap());
|
||||
let decoder = crate::Decoder::new(File::open(path).unwrap());
|
||||
let (info, mut reader) = decoder.read_info().unwrap();
|
||||
if info.line_size != 32 {
|
||||
// TODO encoding only works with line size 32?
|
||||
@ -203,7 +346,54 @@ mod tests {
|
||||
encoder.write_image_data(&buf).unwrap();
|
||||
}
|
||||
// Decode encoded decoded image
|
||||
let decoder = ::Decoder::new(&*out);
|
||||
let decoder = crate::Decoder::new(&*out);
|
||||
let (info, mut reader) = decoder.read_info().unwrap();
|
||||
let mut buf2 = vec![0; info.buffer_size()];
|
||||
reader.next_frame(&mut buf2).unwrap();
|
||||
// check if the encoded image is ok:
|
||||
assert_eq!(buf, buf2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip_stream() {
|
||||
// More loops = more random testing, but also more test wait time
|
||||
for _ in 0..10 {
|
||||
for path in glob::glob("tests/pngsuite/*.png").unwrap().map(|r| r.unwrap()) {
|
||||
if path.file_name().unwrap().to_str().unwrap().starts_with("x") {
|
||||
// x* files are expected to fail to decode
|
||||
continue;
|
||||
}
|
||||
// Decode image
|
||||
let decoder = crate::Decoder::new(File::open(path).unwrap());
|
||||
let (info, mut reader) = decoder.read_info().unwrap();
|
||||
if info.line_size != 32 {
|
||||
// TODO encoding only works with line size 32?
|
||||
continue;
|
||||
}
|
||||
let mut buf = vec![0; info.buffer_size()];
|
||||
reader.next_frame(&mut buf).unwrap();
|
||||
// Encode decoded image
|
||||
let mut out = Vec::new();
|
||||
{
|
||||
let mut wrapper = RandomChunkWriter {
|
||||
rng: self::rand::thread_rng(),
|
||||
w: &mut out
|
||||
};
|
||||
|
||||
let mut encoder = Encoder::new(&mut wrapper, info.width, info.height).write_header().unwrap();
|
||||
let mut stream_writer = encoder.stream_writer();
|
||||
|
||||
let mut outer_wrapper = RandomChunkWriter {
|
||||
rng: self::rand::thread_rng(),
|
||||
w: &mut stream_writer
|
||||
};
|
||||
|
||||
outer_wrapper.write_all(&buf).unwrap();
|
||||
}
|
||||
// Decode encoded decoded image
|
||||
let decoder = crate::Decoder::new(&*out);
|
||||
let (info, mut reader) = decoder.read_info().unwrap();
|
||||
let mut buf2 = vec![0; info.buffer_size()];
|
||||
reader.next_frame(&mut buf2).unwrap();
|
||||
@ -223,8 +413,8 @@ mod tests {
|
||||
let output = vec![0u8; 1024];
|
||||
let writer = Cursor::new(output);
|
||||
let mut encoder = Encoder::new(writer, width as u32, height as u32);
|
||||
encoder.set(BitDepth::Eight);
|
||||
encoder.set(ColorType::RGB);
|
||||
encoder.set_depth(BitDepth::Eight);
|
||||
encoder.set_color(ColorType::RGB);
|
||||
let mut png_writer = encoder.write_header()?;
|
||||
|
||||
let correct_image_size = width * height * 3;
|
||||
@ -254,4 +444,4 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
5
third_party/rust/png/src/filter.rs
vendored
5
third_party/rust/png/src/filter.rs
vendored
@ -1,5 +1,10 @@
|
||||
use std;
|
||||
|
||||
/// The byte level filter applied to scanlines to prepare them for compression.
|
||||
///
|
||||
/// Compression in general benefits from repetitive data. The filter is a content-aware method of
|
||||
/// compressing the range of occurring byte values to help the compression algorithm. Note that
|
||||
/// this does not operate on pixels but on raw bytes of a scanline.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum FilterType {
|
||||
|
41
third_party/rust/png/src/lib.rs
vendored
41
third_party/rust/png/src/lib.rs
vendored
@ -21,33 +21,30 @@
|
||||
//! ## Encoder
|
||||
//! ### Using the encoder
|
||||
//! ```ignore
|
||||
//! // For reading and opening files
|
||||
//! use std::path::Path;
|
||||
//! use std::fs::File;
|
||||
//! use std::io::BufWriter;
|
||||
//! // To use encoder.set()
|
||||
//! use png::HasParameters;
|
||||
//! // For reading and opening files
|
||||
//! use std::path::Path;
|
||||
//! use std::fs::File;
|
||||
//! use std::io::BufWriter;
|
||||
//! // To use encoder.set()
|
||||
//! use png::HasParameters;
|
||||
//!
|
||||
//! let path = Path::new(r"/path/to/image.png");
|
||||
//! let file = File::create(path).unwrap();
|
||||
//! let ref mut w = BufWriter::new(file);
|
||||
//! let path = Path::new(r"/path/to/image.png");
|
||||
//! let file = File::create(path).unwrap();
|
||||
//! let ref mut w = BufWriter::new(file);
|
||||
//!
|
||||
//! let mut encoder = png::Encoder::new(w, 2, 1); // Width is 2 pixels and height is 1.
|
||||
//! encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight);
|
||||
//! let mut writer = encoder.write_header().unwrap();
|
||||
//! let mut encoder = png::Encoder::new(w, 2, 1); // Width is 2 pixels and height is 1.
|
||||
//! encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight);
|
||||
//! let mut writer = encoder.write_header().unwrap();
|
||||
//!
|
||||
//! let data = [255, 0, 0, 255, 0, 0, 0, 255]; // An array containing a RGBA sequence. First pixel is red and second pixel is black.
|
||||
//! writer.write_image_data(&data).unwrap(); // Save
|
||||
//! let data = [255, 0, 0, 255, 0, 0, 0, 255]; // An array containing a RGBA sequence. First pixel is red and second pixel is black.
|
||||
//! writer.write_image_data(&data).unwrap(); // Save
|
||||
//! ```
|
||||
//!
|
||||
//#![cfg_attr(test, feature(test))]
|
||||
|
||||
#[macro_use] extern crate bitflags;
|
||||
|
||||
extern crate num_iter;
|
||||
|
||||
pub mod chunk;
|
||||
mod crc;
|
||||
mod decoder;
|
||||
#[cfg(feature = "png-encoding")]
|
||||
mod encoder;
|
||||
@ -56,10 +53,8 @@ mod traits;
|
||||
mod common;
|
||||
mod utils;
|
||||
|
||||
pub use common::*;
|
||||
pub use decoder::{Decoder, Reader, OutputInfo, StreamingDecoder, Decoded, DecodingError, Limits};
|
||||
pub use crate::common::*;
|
||||
pub use crate::decoder::{Decoder, Reader, OutputInfo, StreamingDecoder, Decoded, DecodingError, Limits};
|
||||
#[cfg(feature = "png-encoding")]
|
||||
pub use encoder::{Encoder, Writer, EncodingError};
|
||||
pub use filter::FilterType;
|
||||
|
||||
pub use traits::{Parameter, HasParameters};
|
||||
pub use crate::encoder::{Encoder, Writer, StreamWriter, EncodingError};
|
||||
pub use crate::filter::FilterType;
|
||||
|
22
third_party/rust/png/src/traits.rs
vendored
22
third_party/rust/png/src/traits.rs
vendored
@ -1,19 +1,5 @@
|
||||
use std::io;
|
||||
|
||||
/// Configuration parameter trait
|
||||
pub trait Parameter<Object> {
|
||||
fn set_param(self, &mut Object);
|
||||
}
|
||||
|
||||
/// Object has parameters
|
||||
pub trait HasParameters: Sized {
|
||||
fn set<T: Parameter<Self>>(&mut self, value: T) -> &mut Self {
|
||||
value.set_param(self);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Will be replaced by stdlib solution
|
||||
fn read_all<R: io::Read + ?Sized>(this: &mut R, buf: &mut [u8]) -> io::Result<()> {
|
||||
let mut total = 0;
|
||||
@ -39,7 +25,7 @@ pub trait ReadBytesExt<T>: io::Read {
|
||||
/// Write extension to write big endian data
|
||||
pub trait WriteBytesExt<T>: io::Write {
|
||||
/// Writes `T` to a bytes stream. Most significant byte first.
|
||||
fn write_be(&mut self, T) -> io::Result<()>;
|
||||
fn write_be(&mut self, _: T) -> io::Result<()>;
|
||||
|
||||
}
|
||||
|
||||
@ -47,7 +33,7 @@ impl<W: io::Read + ?Sized> ReadBytesExt<u8> for W {
|
||||
#[inline]
|
||||
fn read_be(&mut self) -> io::Result<u8> {
|
||||
let mut byte = [0];
|
||||
try!(read_all(self, &mut byte));
|
||||
read_all(self, &mut byte)?;
|
||||
Ok(byte[0])
|
||||
}
|
||||
}
|
||||
@ -55,7 +41,7 @@ impl<W: io::Read + ?Sized> ReadBytesExt<u16> for W {
|
||||
#[inline]
|
||||
fn read_be(&mut self) -> io::Result<u16> {
|
||||
let mut bytes = [0, 0];
|
||||
try!(read_all(self, &mut bytes));
|
||||
read_all(self, &mut bytes)?;
|
||||
Ok((bytes[0] as u16) << 8 | bytes[1] as u16)
|
||||
}
|
||||
}
|
||||
@ -64,7 +50,7 @@ impl<W: io::Read + ?Sized> ReadBytesExt<u32> for W {
|
||||
#[inline]
|
||||
fn read_be(&mut self) -> io::Result<u32> {
|
||||
let mut bytes = [0, 0, 0, 0];
|
||||
try!(read_all(self, &mut bytes));
|
||||
read_all(self, &mut bytes)?;
|
||||
Ok( (bytes[0] as u32) << 24
|
||||
| (bytes[1] as u32) << 16
|
||||
| (bytes[2] as u32) << 8
|
||||
|
233
third_party/rust/png/src/utils.rs
vendored
233
third_party/rust/png/src/utils.rs
vendored
@ -1,6 +1,6 @@
|
||||
//! Utility functions
|
||||
use std::iter::repeat;
|
||||
use num_iter::range_step;
|
||||
use std::iter::{repeat, StepBy};
|
||||
use std::ops::Range;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn unpack_bits<F>(buf: &mut [u8], channels: usize, bit_depth: u8, func: F)
|
||||
@ -21,13 +21,11 @@ where F: Fn(u8, &mut[u8]) {
|
||||
.rev() // reverse iterator
|
||||
.flat_map(|idx|
|
||||
// this has to be reversed too
|
||||
range_step(0, 8, bit_depth)
|
||||
(0..8).step_by(bit_depth.into())
|
||||
.zip(repeat(idx))
|
||||
)
|
||||
.skip(skip);
|
||||
let channels = channels as isize;
|
||||
let j = range_step(buf.len() as isize - channels, -channels, -channels);
|
||||
//let j = range_step(0, buf.len(), channels).rev(); // ideal solution;
|
||||
let j = (0..=buf.len() - channels).rev().step_by(channels);
|
||||
for ((shift, i), j) in i.zip(j) {
|
||||
let pixel = (buf[i] & (mask << shift)) >> shift;
|
||||
func(pixel, &mut buf[j as usize..(j + channels) as usize])
|
||||
@ -35,10 +33,8 @@ where F: Fn(u8, &mut[u8]) {
|
||||
}
|
||||
|
||||
pub fn expand_trns_line(buf: &mut[u8], trns: &[u8], channels: usize) {
|
||||
let channels = channels as isize;
|
||||
let i = range_step(buf.len() as isize / (channels+1) * channels - channels, -channels, -channels);
|
||||
let j = range_step(buf.len() as isize - (channels+1), -(channels+1), -(channels+1));
|
||||
let channels = channels as usize;
|
||||
let i = (0..=buf.len() / (channels+1) * channels - channels).rev().step_by(channels);
|
||||
let j = (0..=buf.len() - (channels+1)).rev().step_by(channels+1);
|
||||
for (i, j) in i.zip(j) {
|
||||
let i_pixel = i as usize;
|
||||
let j_chunk = j as usize;
|
||||
@ -54,11 +50,9 @@ pub fn expand_trns_line(buf: &mut[u8], trns: &[u8], channels: usize) {
|
||||
}
|
||||
|
||||
pub fn expand_trns_line16(buf: &mut[u8], trns: &[u8], channels: usize) {
|
||||
let channels = channels as isize;
|
||||
let c2 = 2 * channels;
|
||||
let i = range_step(buf.len() as isize / (c2+2) * c2 - c2, -c2, -c2);
|
||||
let j = range_step(buf.len() as isize - (c2+2), -(c2+2), -(c2+2));
|
||||
let c2 = c2 as usize;
|
||||
let i = (0..=buf.len() / (c2+2) * c2 - c2).rev().step_by(c2);
|
||||
let j = (0..=buf.len() - (c2+2)).rev().step_by(c2+2);
|
||||
for (i, j) in i.zip(j) {
|
||||
let i_pixel = i as usize;
|
||||
let j_chunk = j as usize;
|
||||
@ -155,33 +149,76 @@ impl Iterator for Adam7Iterator {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! expand_pass(
|
||||
($img:expr, $scanline:expr, $j:ident, $pos:expr, $bytes_pp:expr) => {
|
||||
for ($j, pixel) in $scanline.chunks($bytes_pp).enumerate() {
|
||||
for (offset, val) in pixel.iter().enumerate() {
|
||||
$img[$pos + offset] = *val
|
||||
}
|
||||
fn subbyte_pixels<'a>(scanline: &'a [u8], bits_pp: usize) -> impl Iterator<Item=u8> + 'a {
|
||||
(0..scanline.len() * 8).step_by(bits_pp).map(move |bit_idx| {
|
||||
let byte_idx = bit_idx / 8;
|
||||
|
||||
// sub-byte samples start in the high-order bits
|
||||
let rem = 8 - bit_idx % 8 - bits_pp;
|
||||
|
||||
match bits_pp {
|
||||
// evenly divides bytes
|
||||
1 => (scanline[byte_idx] >> rem) & 1,
|
||||
2 => (scanline[byte_idx] >> rem) & 3,
|
||||
4 => (scanline[byte_idx] >> rem) & 15,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
/// Given pass, image width, and line number, produce an iterator of bit positions of pixels to copy
|
||||
/// from the input scanline to the image buffer.
|
||||
fn expand_adam7_bits(pass: u8, width: usize, line_no: usize, bits_pp: usize) -> StepBy<Range<usize>> {
|
||||
let (line_mul, line_off, samp_mul, samp_off) = match pass {
|
||||
1 => (8, 0, 8, 0),
|
||||
2 => (8, 0, 8, 4),
|
||||
3 => (8, 4, 4, 0),
|
||||
4 => (4, 0, 4, 2),
|
||||
5 => (4, 2, 2, 0),
|
||||
6 => (2, 0, 2, 1),
|
||||
7 => (2, 1, 1, 0),
|
||||
_ => panic!("Adam7 pass out of range: {}", pass)
|
||||
};
|
||||
|
||||
// the equivalent line number in progressive scan
|
||||
let prog_line = line_mul * line_no + line_off;
|
||||
// line width is rounded up to the next byte
|
||||
let line_width = width * bits_pp + 7 & !7;
|
||||
let line_start = prog_line * line_width;
|
||||
let start = line_start + (samp_off * bits_pp);
|
||||
let stop = line_start + (width * bits_pp);
|
||||
|
||||
(start .. stop).step_by(bits_pp * samp_mul)
|
||||
}
|
||||
|
||||
/// Expands an Adam 7 pass
|
||||
pub fn expand_pass(
|
||||
img: &mut [u8], width: u32, scanline: &[u8],
|
||||
pass: u8, line_no: u32, bytes_pp: u8) {
|
||||
let line_no = line_no as usize;
|
||||
pass: u8, line_no: u32, bits_pp: u8) {
|
||||
|
||||
let width = width as usize;
|
||||
let bytes_pp = bytes_pp as usize;
|
||||
match pass {
|
||||
1 => expand_pass!(img, scanline, j, 8*line_no * width + bytes_pp * j*8 , bytes_pp),
|
||||
2 => expand_pass!(img, scanline, j, 8*line_no * width + bytes_pp *(j*8 + 4), bytes_pp),
|
||||
3 => expand_pass!(img, scanline, j, (8*line_no+4) * width + bytes_pp * j*4 , bytes_pp),
|
||||
4 => expand_pass!(img, scanline, j, 4*line_no * width + bytes_pp *(j*4 + 2), bytes_pp),
|
||||
5 => expand_pass!(img, scanline, j, (4*line_no+2) * width + bytes_pp * j*2 , bytes_pp),
|
||||
6 => expand_pass!(img, scanline, j, 2*line_no * width + bytes_pp *(j*2+1) , bytes_pp),
|
||||
7 => expand_pass!(img, scanline, j, (2*line_no+1) * width + bytes_pp * j , bytes_pp),
|
||||
_ => {}
|
||||
}
|
||||
let line_no = line_no as usize;
|
||||
let bits_pp = bits_pp as usize;
|
||||
|
||||
// pass is out of range but don't blow up
|
||||
if pass == 0 || pass > 7 { return; }
|
||||
|
||||
let bit_indices = expand_adam7_bits(pass, width, line_no, bits_pp);
|
||||
|
||||
if bits_pp < 8 {
|
||||
for (pos, px) in bit_indices.zip(subbyte_pixels(scanline, bits_pp)) {
|
||||
let rem = 8 - pos % 8 - bits_pp;
|
||||
img[pos / 8] |= px << rem as u8;
|
||||
}
|
||||
} else {
|
||||
let bytes_pp = bits_pp / 8;
|
||||
|
||||
for (bitpos, px) in bit_indices.zip(scanline.chunks(bytes_pp)) {
|
||||
for (offset, val) in px.iter().enumerate() {
|
||||
img[bitpos / 8 + offset] = *val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -196,3 +233,129 @@ fn test_adam7() {
|
||||
let passes: Vec<_> = it.collect();
|
||||
assert_eq!(&*passes, &[(1, 0, 1), (4, 0, 1), (5, 0, 2), (6, 0, 2), (6, 1, 2), (7, 0, 4), (7, 1, 4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subbyte_pixels() {
|
||||
let scanline = &[0b10101010, 0b10101010];
|
||||
|
||||
|
||||
let pixels = subbyte_pixels(scanline, 1).collect::<Vec<_>>();
|
||||
assert_eq!(pixels.len(), 16);
|
||||
assert_eq!(pixels, [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expand_adam7_bits() {
|
||||
let width = 32;
|
||||
let bits_pp = 1;
|
||||
|
||||
let expected = |offset: usize, step: usize, count: usize| (0 .. count).map(move |i| step * i + offset).collect::<Vec<_>>();
|
||||
|
||||
for line_no in 0..8 {
|
||||
let start = 8 * line_no * width;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(1, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 8, 4)
|
||||
);
|
||||
|
||||
let start = start + 4;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(2, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 8, 4)
|
||||
);
|
||||
|
||||
let start = (8 * line_no + 4) as usize * width as usize;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(3, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 4, 8)
|
||||
);
|
||||
}
|
||||
|
||||
for line_no in 0 .. 16 {
|
||||
let start = 4 * line_no * width + 2;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(4, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 4, 8)
|
||||
);
|
||||
|
||||
let start = (4 * line_no + 2) * width;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(5, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 2, 16)
|
||||
)
|
||||
}
|
||||
|
||||
for line_no in 0 .. 32 {
|
||||
let start = 2 * line_no * width + 1;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(6, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 2, 16),
|
||||
"line_no: {}", line_no
|
||||
);
|
||||
|
||||
let start = (2 * line_no + 1) * width;
|
||||
|
||||
assert_eq!(
|
||||
expand_adam7_bits(7, width, line_no, bits_pp).collect::<Vec<_>>(),
|
||||
expected(start, 1, 32)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expand_pass_subbyte() {
|
||||
let mut img = [0u8; 8];
|
||||
let width = 8;
|
||||
let bits_pp = 1;
|
||||
|
||||
expand_pass(&mut img, width, &[0b10000000], 1, 0, bits_pp);
|
||||
assert_eq!(img, [0b10000000u8, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b10000000], 2, 0, bits_pp);
|
||||
assert_eq!(img, [0b10001000u8, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11000000], 3, 0, bits_pp);
|
||||
assert_eq!(img, [0b10001000u8, 0, 0, 0, 0b10001000, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11000000], 4, 0, bits_pp);
|
||||
assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10001000, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11000000], 4, 1, bits_pp);
|
||||
assert_eq!(img, [0b10101010u8, 0, 0, 0, 0b10101010, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 5, 0, bits_pp);
|
||||
assert_eq!(img, [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 5, 1, bits_pp);
|
||||
assert_eq!(img, [0b10101010u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 6, 0, bits_pp);
|
||||
assert_eq!(img, [0b11111111u8, 0, 0b10101010, 0, 0b10101010, 0, 0b10101010, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 6, 1, bits_pp);
|
||||
assert_eq!(img, [0b11111111u8, 0, 0b11111111, 0, 0b10101010, 0, 0b10101010, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 6, 2, bits_pp);
|
||||
assert_eq!(img, [0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b10101010, 0]);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11110000], 6, 3, bits_pp);
|
||||
assert_eq!([0b11111111u8, 0, 0b11111111, 0, 0b11111111, 0, 0b11111111, 0], img);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11111111], 7, 0, bits_pp);
|
||||
assert_eq!([0b11111111u8, 0b11111111, 0b11111111, 0, 0b11111111, 0, 0b11111111, 0], img);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11111111], 7, 1, bits_pp);
|
||||
assert_eq!([0b11111111u8, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0, 0b11111111, 0], img);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11111111], 7, 2, bits_pp);
|
||||
assert_eq!([0b11111111u8, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0], img);
|
||||
|
||||
expand_pass(&mut img, width, &[0b11111111], 7, 3, bits_pp);
|
||||
assert_eq!([0b11111111u8, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111], img);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user