From 6e82372485fc5185b6fcd24ad397c3add7ea1399 Mon Sep 17 00:00:00 2001 From: Sam Blazes Date: Wed, 12 Jun 2024 20:58:37 -0400 Subject: [PATCH] initial commit --- .gitignore | 1 + Cargo.lock | 21 + Cargo.toml | 7 + README.md | 14 + artspace.rs | 132 +++ src/main.rs | 132 +++ test_image.jpg | Bin 0 -> 580864 bytes third_party/zune-core/CHANGELOG.md | 22 + third_party/zune-core/Cargo.toml | 22 + third_party/zune-core/LICENSE-APACHE | 1 + third_party/zune-core/LICENSE-MIT | 1 + third_party/zune-core/LICENSE-ZLIB | 1 + third_party/zune-core/README.md | 15 + third_party/zune-core/src/bit_depth.rs | 170 ++++ third_party/zune-core/src/bytestream.rs | 27 + .../zune-core/src/bytestream/reader.rs | 458 +++++++++ .../src/bytestream/reader/no_std_readers.rs | 198 ++++ .../src/bytestream/reader/std_readers.rs | 100 ++ .../zune-core/src/bytestream/traits.rs | 146 +++ .../zune-core/src/bytestream/writer.rs | 262 +++++ .../src/bytestream/writer/no_std_writer.rs | 70 ++ .../src/bytestream/writer/std_writer.rs | 27 + third_party/zune-core/src/colorspace.rs | 161 ++++ third_party/zune-core/src/lib.rs | 62 ++ third_party/zune-core/src/log.rs | 74 ++ third_party/zune-core/src/options.rs | 13 + third_party/zune-core/src/options/decoder.rs | 666 +++++++++++++ third_party/zune-core/src/options/encoder.rs | 217 +++++ third_party/zune-core/src/result.rs | 72 ++ third_party/zune-core/src/serde.rs | 63 ++ third_party/zune-jpeg/.gitignore | 1 + third_party/zune-jpeg/Benches.md | 79 ++ third_party/zune-jpeg/Cargo.toml | 26 + third_party/zune-jpeg/Changelog.md | 64 ++ third_party/zune-jpeg/LICENSE-APACHE | 1 + third_party/zune-jpeg/LICENSE-MIT | 1 + third_party/zune-jpeg/LICENSE-ZLIB | 1 + third_party/zune-jpeg/README.md | 104 ++ third_party/zune-jpeg/fuzz/.gitignore | 3 + third_party/zune-jpeg/fuzz/Cargo.toml | 32 + .../fuzz/fuzz_targets/decode_buffer.rs | 10 + .../zune-jpeg/fuzz/fuzz_targets/fuzz_idct.rs | 47 + third_party/zune-jpeg/src/bitstream.rs | 671 +++++++++++++ third_party/zune-jpeg/src/color_convert.rs | 89 ++ .../zune-jpeg/src/color_convert/avx.rs | 350 +++++++ .../zune-jpeg/src/color_convert/scalar.rs | 116 +++ third_party/zune-jpeg/src/components.rs | 211 ++++ third_party/zune-jpeg/src/decoder.rs | 910 ++++++++++++++++++ third_party/zune-jpeg/src/errors.rs | 167 ++++ third_party/zune-jpeg/src/headers.rs | 544 +++++++++++ third_party/zune-jpeg/src/huffman.rs | 254 +++++ third_party/zune-jpeg/src/idct.rs | 147 +++ third_party/zune-jpeg/src/idct/avx2.rs | 288 ++++++ third_party/zune-jpeg/src/idct/neon.rs | 296 ++++++ third_party/zune-jpeg/src/idct/scalar.rs | 212 ++++ third_party/zune-jpeg/src/lib.rs | 133 +++ third_party/zune-jpeg/src/marker.rs | 85 ++ third_party/zune-jpeg/src/mcu.rs | 504 ++++++++++ third_party/zune-jpeg/src/mcu_prog.rs | 617 ++++++++++++ third_party/zune-jpeg/src/misc.rs | 431 +++++++++ third_party/zune-jpeg/src/unsafe_utils.rs | 4 + .../zune-jpeg/src/unsafe_utils_avx2.rs | 223 +++++ .../zune-jpeg/src/unsafe_utils_neon.rs | 331 +++++++ third_party/zune-jpeg/src/upsampler.rs | 101 ++ third_party/zune-jpeg/src/upsampler/scalar.rs | 110 +++ third_party/zune-jpeg/src/worker.rs | 429 +++++++++ third_party/zune-jpeg/tests/invalid_images.rs | 66 ++ 67 files changed, 10813 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 artspace.rs create mode 100644 src/main.rs create mode 100644 test_image.jpg create mode 100644 third_party/zune-core/CHANGELOG.md create mode 100644 third_party/zune-core/Cargo.toml create mode 100644 third_party/zune-core/LICENSE-APACHE create mode 100644 third_party/zune-core/LICENSE-MIT create mode 100644 third_party/zune-core/LICENSE-ZLIB create mode 100644 third_party/zune-core/README.md create mode 100644 third_party/zune-core/src/bit_depth.rs create mode 100644 third_party/zune-core/src/bytestream.rs create mode 100644 third_party/zune-core/src/bytestream/reader.rs create mode 100644 third_party/zune-core/src/bytestream/reader/no_std_readers.rs create mode 100644 third_party/zune-core/src/bytestream/reader/std_readers.rs create mode 100644 third_party/zune-core/src/bytestream/traits.rs create mode 100644 third_party/zune-core/src/bytestream/writer.rs create mode 100644 third_party/zune-core/src/bytestream/writer/no_std_writer.rs create mode 100644 third_party/zune-core/src/bytestream/writer/std_writer.rs create mode 100644 third_party/zune-core/src/colorspace.rs create mode 100644 third_party/zune-core/src/lib.rs create mode 100644 third_party/zune-core/src/log.rs create mode 100644 third_party/zune-core/src/options.rs create mode 100644 third_party/zune-core/src/options/decoder.rs create mode 100644 third_party/zune-core/src/options/encoder.rs create mode 100644 third_party/zune-core/src/result.rs create mode 100644 third_party/zune-core/src/serde.rs create mode 100644 third_party/zune-jpeg/.gitignore create mode 100644 third_party/zune-jpeg/Benches.md create mode 100644 third_party/zune-jpeg/Cargo.toml create mode 100644 third_party/zune-jpeg/Changelog.md create mode 100644 third_party/zune-jpeg/LICENSE-APACHE create mode 100644 third_party/zune-jpeg/LICENSE-MIT create mode 100644 third_party/zune-jpeg/LICENSE-ZLIB create mode 100644 third_party/zune-jpeg/README.md create mode 100644 third_party/zune-jpeg/fuzz/.gitignore create mode 100644 third_party/zune-jpeg/fuzz/Cargo.toml create mode 100644 third_party/zune-jpeg/fuzz/fuzz_targets/decode_buffer.rs create mode 100644 third_party/zune-jpeg/fuzz/fuzz_targets/fuzz_idct.rs create mode 100644 third_party/zune-jpeg/src/bitstream.rs create mode 100644 third_party/zune-jpeg/src/color_convert.rs create mode 100644 third_party/zune-jpeg/src/color_convert/avx.rs create mode 100644 third_party/zune-jpeg/src/color_convert/scalar.rs create mode 100644 third_party/zune-jpeg/src/components.rs create mode 100644 third_party/zune-jpeg/src/decoder.rs create mode 100644 third_party/zune-jpeg/src/errors.rs create mode 100644 third_party/zune-jpeg/src/headers.rs create mode 100644 third_party/zune-jpeg/src/huffman.rs create mode 100644 third_party/zune-jpeg/src/idct.rs create mode 100644 third_party/zune-jpeg/src/idct/avx2.rs create mode 100644 third_party/zune-jpeg/src/idct/neon.rs create mode 100644 third_party/zune-jpeg/src/idct/scalar.rs create mode 100644 third_party/zune-jpeg/src/lib.rs create mode 100644 third_party/zune-jpeg/src/marker.rs create mode 100644 third_party/zune-jpeg/src/mcu.rs create mode 100644 third_party/zune-jpeg/src/mcu_prog.rs create mode 100644 third_party/zune-jpeg/src/misc.rs create mode 100644 third_party/zune-jpeg/src/unsafe_utils.rs create mode 100644 third_party/zune-jpeg/src/unsafe_utils_avx2.rs create mode 100644 third_party/zune-jpeg/src/unsafe_utils_neon.rs create mode 100644 third_party/zune-jpeg/src/upsampler.rs create mode 100644 third_party/zune-jpeg/src/upsampler/scalar.rs create mode 100644 third_party/zune-jpeg/src/worker.rs create mode 100644 third_party/zune-jpeg/tests/invalid_images.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..db84dac --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,21 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "artspace" +version = "0.1.0" +dependencies = [ + "zune-jpeg", +] + +[[package]] +name = "zune-core" +version = "0.5.0-rc1" + +[[package]] +name = "zune-jpeg" +version = "0.5.0-rc1" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..fb5e554 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "artspace" +version = "0.1.0" +edition = "2021" + +[dependencies] +zune-jpeg = {path = "third_party/zune-jpeg"} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c2b669 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +artspace +======== + +Tabs or spaces, the eternal question. Why limit yourself to whitespace that doesn't even make a visual difference? + +Instead, turn that wasted whitespace into artspace! + +## Usage + +``` +cargo run --release -- test_image.jpg src\main.rs artspace.rs +``` + +Note: Only compatible with languages with `/* this style of multi-line comment */`. \ No newline at end of file diff --git a/artspace.rs b/artspace.rs new file mode 100644 index 0000000..5582812 --- /dev/null +++ b/artspace.rs @@ -0,0 +1,132 @@ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇ ⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⣀⣾⣿⣿⣿⣿⣿*/ +pub fn convert_bitmap_to_unicode(w: usize, h: usize, data: Vec) -> Vec>/*⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠓ ⣈⣬⣿⣿⣿⣿⣿⣿⣿*/ +{/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⡷⠓ ⢀⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿*/ +/**/const CHARS: [&str; 4] = [/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ */ +/*⣿⣿⣿⣿*/" ⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿",/* ⣈⣾⣿⣿⣿⣿⣿⣿⣿⡿⠓⠁ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ */ +/*⣿⣿⣿⣿*/"⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿",/*⣾⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ */ +/*⣿⣿⣿⣿*/"⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿",/*⣿⣿⣿⣿⣿⣿⣿⠗ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ */ +/*⣿⣿⣿⣿*/"⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿",/*⣿⣿⣿⣿⣿⠷⠁ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ */ +/**/];/* ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠑ */ +/**/let bitchars = CHARS.iter().flat_map(|t| t.chars()).collect::>();/*⣿⠷ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠑ */ +/*⣿⣿⣿⠿ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢌ ⣼⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠓⠁ ⢀*/ +/**/let px = |i: usize, j: usize| if i < w && j < h {data[j * w + i]} else {0};/* ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⢀⣬⣿*/ +/*⣿⠿ ⣨⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯ ⣠⣿⣿⣿⣿⣿⣿⣿⠷ ⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⣬⣿⣿⣿*/ +/**/let mut output = vec![];/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢏ ⣿⣿⣿⣿⣿⣿⣿⠿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣰⣿⣿⣿⣿*/ +/*⣿ ⣼⣿⣿⣿⣿⣿⣿⣿⠇ ⡰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣠⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠈ ⣀⣿⣿⣿⣿⣿*/ +/**/for j in (0..h).step_by(4)/* ⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣸⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⢀⣿⣿⣿⣿⣿⣿*/ +/**/{/* ⣼⣿⣿⣿⣿⣿⣿⣿⠟ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⣿⠇ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢌ ⣰⣿⣿⣿⣿⣿⣿*/ +/* */let mut line = vec![];/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿ ⠰⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⢌ ⣷⣿⣿⣿⣿⣿*/ +/* */for i in (0..w).step_by(2)/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠱⡳⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⠱⣷⣿⣿⣿*/ +/* */{/*⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠑⠱⠳⡷⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎ ⠐⡳⣿*/ +/* */let mut index = 0;/* ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠐⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣯ ⠐*/ +/* ⣸*/index |= if px(i+0, j+0) < 128 {0} else {1 << 0};/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠱⣷⣿⣿⣿⣿⣿⣿⠷ */ +/* ⢀⣿*/index |= if px(i+0, j+1) < 128 {0} else {1 << 1};/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇ ⣳⣿⣿⣿⠷⠓ */ +/* ⣸⣿*/index |= if px(i+0, j+2) < 128 {0} else {1 << 2};/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ ⢈⣌⣬⣮⣮⣮⣎⣌⣌⣌⣌⣾⣿⡿⠁ */ +/* ⣀⣿⣿*/index |= if px(i+0, j+3) < 128 {0} else {1 << 3};/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⢀⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢌ */ +/* ⣈⣿⣿⣿*/index |= if px(i+1, j+0) < 128 {0} else {1 << 4};/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⣈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣌⠈ */ +/* ⢀⣼⣿⣿⣿⣿*/index |= if px(i+1, j+1) < 128 {0} else {1 << 5};/*⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢌ */ +/*⢌⢈⣿⣿⣿⣿⣿⣿*/index |= if px(i+1, j+2) < 128 {0} else {1 << 6};/*⣿⣿⣿⣿⣿⣿⠷ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⡷⡷⡷⣿⣿⣿⣿⣿⣯⣎⢈ ⣴*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/index |= if px(i+1, j+3) < 128 {0} else {1 << 7};/*⣿⣿⣿⣿⡷⠃ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⠑⡳⣿⣿⣿⣿⣿⣿⣮⣮⣮⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠁ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/line.push(bitchars[index]);/* ⠱⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠳⠑ ⣈⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷ ⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/}/*⠟ ⣾⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⠐⠱⡷⣷⣿⡷⡷⠳⠑⠁ ⢀⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/output.push(line);/*⣿⣿⣿⣿⣿⣿⣿⣿⣎⢌ ⢀⣌⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/**/}/*⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣌⢈⠈ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣮⣌⢈ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠑ ⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/**/output/* ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⠈⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠓⣳*/ +}/*⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠓⠑⠑⠑⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠈ ⢀⡈⣚⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠓ ⢈⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⢈⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ ⢈⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⠟ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⣌⢈⢈⢈⣌⣬⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠓ ⢀⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ */ +fn read_jpeg_to_bitmap(file: &str) -> (usize, usize, Vec)/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿ */ +{/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣷⣿⣿⣿⣿⣿⣿⠿ ⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ */ +/**/use zune_jpeg::zune_core::{colorspace::ColorSpace, options::DecoderOptions, bytestream::ZCursor};/*⣿⣿⣿⣿⣿⠁ */ +/**/let data = std::fs::read(file).unwrap();/* ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠁ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +/**/let options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::Luma);/*⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ */ +/**/let mut decoder = zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&data), options);/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ */ +/**/let pixels = decoder.decode().unwrap();/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠁ ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁ */ +/**/let (w, h) = decoder.dimensions().unwrap();/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠗ */ +/**/(w, h, pixels)/*⣯⣌⣌⣬⣾⣿⣿⣿⠎ ⢬⣭⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +}/* ⠰⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⣐⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +/*⣯⠌ ⠐⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠈ ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +/*⣿⣿⠌ ⠐⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯ */ +fn main()/* ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁ ⡰⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ */ +{/*⣿⣿⠏ ⣱⣿⣿⣿⣿⣿⣿⣿⠿ ⣳⣿⣿⣿⣿⣿⣿⣿⠿ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ */ +/**/match std::env::args().collect::>().as_slice() {/*⣿⣿⣿⣿⣿⣿⣿⠌ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ */ +/*⣿⣿⣿⣿*/[_, bitmap_file, source_file, output_file] =>/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢌ ⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ */ +/*⣿⣿⣿⣿*/{/* ⠰⣿⣿⣿⣿⣿⣿⣿⣏ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⠈ */ +/*⣿⣿⣿⣿⣿ */let (w, h, pixels) = read_jpeg_to_bitmap(&bitmap_file);/*⣿⣿⣯⢌ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⣌⢌⢈⢈⢈⢈*/ +/*⣿⣿⣿⣿⣿⠏ ⡰⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑⠑⠑⠱⣷⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⢀⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿ */let char_bitmap = convert_bitmap_to_unicode(w, h, pixels);/*⣿⣿⣿⣯⣎⢈ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠳⠳⠑⠑⠑⠑⠑⠑⠳⡳⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⢏ ⠐⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠓ ⠑⠳⣷⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⠌*/let source = std::fs::read_to_string(source_file).unwrap();/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⠐⠳⣷⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣯ ⡱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎ ⡰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢏ ⡱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓ ⠐⠱⠳⡷*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/let max_width = 120;/*⣏ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠰⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠈ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/let mut modified_lines = vec![];/* ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⠁ ⠱⡳⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⢈⢈⢈⢈⢈⢈⢈⠈ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/let mut buffer = Vec::with_capacity(1024);/*⣿⣿⣿⠿ ⠑⠱⠳⠳⠓⠁ ⢈⣌⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣌⠈ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/let mut row = 0;/*⣿⣿⣿⣿⣿⣿⣿⣿⣎ ⠐⠑⠑⠁ ⢀⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⢌⠈ */ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⢏ ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⠈ ⢀⢈⣌⣮⣮⣎⣌⢈ ⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/for line in source.lines()/*⣿⢎ ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⢀⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/{/* ⢀⣜⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⢌ ⢀⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠷⠳⠳⠳⠳⠳⠳⠳⡷⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⡷⡷⡷⡷⣿⣿⣿⣿⣿⣿*/buffer.clear();/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣮⣌⣬⣮⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠓⠁ ⠐⠱⠳⡷⣿⣿⣿⣿*/ +/*⠓ ⠐⣷⣿⣿⣿⣿*/buffer.extend(line.chars());/*⣯⢌⠈ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑ ⠑⠱⠳*/ +/* ⡳⣿⣿⣿*/if buffer.len() < max_width {/*⣿⣿⣮⢌⠈ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠳⠳⠑⠑⠳⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ */ +/* ⠱⣷⣿⣿⣿⣿⣿*/let needed = max_width - buffer.len();/*⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⠐⠳⣷⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ */ +/* ⠑⠑⠑ */buffer.extend(core::iter::repeat(' ').take(needed));/* ⠐⠱⠳⠳⠳⠳⠑ ⢈⣈⣌⣌⣬⣮⣎⣌⣌⢈ */ +/* */}/* ⠱⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⢌ */ +/* ⢈⣌⣬⣎⢌⠈ ⢈⢈⢈⢈⢈⢈⢈⠈ ⠐⠱⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⢌⠈ */ +/*⣿⣿⣿⣿⣿⣿⣿⠌ */let mut i = 0;/*⣮⣎⣌⢈ ⠱⡳⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠁ ⢈⣌⣌⣌⠈ ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣌⢈⢈⢈*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⢎ */for j in 0..buffer.len()/* ⠐⠱⡳⣷⣿⣿⣿⡿⠓ ⣈⣾⣿⣿⣿⣿⣿⣯⢌ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣌⢈*/{/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣌⠈ ⠁ ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢈ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⡿⠷⠳⠓⠑⠑⠑⠑⠑⠑⠱⡳⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/if !buffer[j].is_whitespace()/* ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⣌⣌⣾⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⠳⠓⠑⠑⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/{/* ⠐⠱⠳⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢌ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⠰⣷⣿⣿⣿⣿⣿⣿⣿⣿*/ +/* ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟ */if j - i > 3/*⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣌⢈ ⣈⣾⣿⣿⣿⣿⣿⡷⡷⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⠐⡳⣿⣿⣿⣿⣿⣿⣿*/ +/* ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */{/* ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣎⢌⠈ ⢈⣬⣾⣿⣿⣿⣿⠷⠑ ⣱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⠐⣳⣿⣿⣿⣿⣿*/ +/* ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯ */let bmp_row = &char_bitmap[row];/*⣿⣿⣿⡿⠃ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⡱⣿⣿⣿⣿*/ +/* ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ */for k in i..j {/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠁ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⠰⣷⣿⣿*/ +/* ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ */buffer[k] = bmp_row[k % bmp_row.len()];/*⣰⣿⣿⣿⣿⣿⣿⣿⣿⠗ ⠐⣷⣿*/ +/* ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠌ */}/* ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇ ⣿⣿⣿⣿⣿⣿⣿⣿⠿ ⣈⣌⢈ ⠐⡳*/ +/*⢀⣌⣾⣿⣿⣿⣿⠷⠑ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ */buffer[i ] = '/';/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ ⣰⣿⣿⣿⣿⣿⣿⣿⡿ ⣀⣾⣿⣿⣿⣯⠈ */ +/*⣿⣿⣿⣿⣿⠿⠁ ⣱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎*/buffer[i+1] = '*';/*⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣀⣿⣿⣿⣿⣿⣿⣿⠈ */ +/*⣿⣿⣿⣿⠗ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/buffer[j-1] = '/';/*⡰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣠⣿⣿⣿⣿⣿⣿⣿⠿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣏ */ +/*⣿⣿⣿⠿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/buffer[j-2] = '*';/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⠇ ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠎ */ +/*⣿⣿⡿ ⣿⣿⣿⣿⣿⣿⣿*/}/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣸⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +/*⣿⣿⠃ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⠿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ */ +/*⣿⠿ ⣿⣿⣿⣿⣿⣿⣿*/i = j + 1;/* ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁ */ +/*⣿⠃ ⣠⣿⣿⣿*/}/*⣿⣿⣿⣿ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ */ +/*⣿⠈ */}/*⣿⣿⣿⣿⣿⣿⣿⣿⣏⠈ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣳⣿⣿⣿⣿⣿⣿⠏ ⡰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣌⢈ */ +/*⣿⣯⠈ ⠐⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠰⣿⣿⣿⣿⣿⣿⣯⠈ ⠱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ */ +/*⣿⣿⣿⠌ */let j = buffer.len();/* ⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣷⣿⣿⣿⣿⣿⣿⣏ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢌ */ +/*⣿⣿⣿⣿⠈ */if j - i > 3/*⣿⣿⣿⣎⠈ ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⢎ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ */ +/*⣿⣿⣿⣿⣏ */{/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢈ ⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⠐⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠯ */ +/*⣿⣿⣿⣿⣿⢎ ⣰*/let bmp_row = &char_bitmap[row];/*⠱⣷⣿⣿⣿⣿⣿⠓ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠈ ⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ ⢈⣬⣮⣿⣿*/ +/*⣳⣿⣿⣿⣿⣿⣎⠈ ⢀⣀⣿*/for k in i..j {/*⣿⣿⣯⢌ ⠐⠳⠳⠳⠁ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯ ⠐⠳⣷⣿⣿⣿⣿⣿⠷⠁ ⢀⣬⣾⣿⣿⣿⣿⣿*/ +/* ⣿⣿⣿⣿⣿⣿⣿⣯⣌⢌⢈⣌⣬⣿⣿⣿⣿⣿⣿*/buffer[k] = bmp_row[k % bmp_row.len()];/* ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⠑⠑⠁ ⣈⣾⣿⣿⣿⣿⣿⣿⣿*/ +/*⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/}/*⠁ ⠑⠱⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/buffer[i ] = '/';/*⣿⣿⣿⣿⣿⣿⣎⢈ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠈ ⢈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿*/buffer[i+1] = '*';/*⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌ ⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⢀⢈⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓ */buffer[j-1] = '/';/*⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢌⠈ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⣈⣮⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟ */buffer[j-2] = '*';/* ⠐⠱⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣎⣌⢈⢈ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑⠑⠱⣷⣿⣿⣿⣿⣿*/ +/* ⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿*/}/* ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠌ ⣰⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣿⣿⣿⣿⣿*/ +/* ⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⢀⣈⣌⣌⣌⢈ ⠐⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓⠑⠑⠑⠑⠳⡷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⡰⣿⣿⣿⣿⣿⣿⣿⠃ ⣰⣿⣿⣿⣿*/ +/* ⡱⣿⣿⣿⣿⣿⣿⣿*/modified_lines.push(buffer.iter().collect::());/* ⠐⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⠈ ⣳⣿⣿⣿⣿⣿⣿ ⣰⣿⣿⣿⣿*/ +/* ⣱⣿⣿⣿⣿⣿⣿*/row += 1;/* ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣯⠈ ⣳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ ⠐⣿⣿⣿⣿⣿⣿ ⣰⣿⣿⣿⣿*/ +/* ⣿⣿⣿*/}/*⣿⣿ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ ⢀⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿*/ +/* ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠎ ⠰⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⡈⣚⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣰⣿⣿⣿⣿⣿⠁ ⠐⣿⣿⣿⣿*/ +/* ⣀⣿⣿⣿⣿*/let new_source = modified_lines.join("\n");/*⠑ ⡀⣚⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⣾⣿⣿⣿⣿⣿ ⣰⣿⣿⣿⣿*/ +/* ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟ ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠎ ⢀⣌⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⣸⣿⣿⣿⣿⣿⣿ ⣰⣿⣿⣿⣿*/ +/* ⣼⣿⣿⣿⣿⣿*/println!("{new_source}");/*⣿⣿⣿⣯ ⢀⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⣼⣿⣿⣿⣿⣿⣿⠿ ⣰⣿⣿⣿⣿*/ +/* ⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⢈⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⠇ ⣰⣿⣿⣿⣿*/ +/*⣀⣿⣿⣿⣿⣿⣿⣿*/std::fs::write(output_file, new_source).unwrap();/*⣌⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠳⠁ ⣈⣿⣿⣿⣿⣿⣿⣿⣿⡿ ⣰⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/}/*⣿⣿⠟ ⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠎ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/[path] =>/* ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏ ⣨⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠑ ⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁ ⣠⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/{/*⣿⠟ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⣀⣿⣿⣿⣿⣿⣿⣿⡿⠷⠓ ⣼⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⣿*/println!("usage: {path} art.jpg input_src output_src");/*⣿⡿⠳⠁ ⡰⣷⡷⡷⠷⠳⠑⠁ ⣨⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/}/*⠇ ⠑⠑ ⠐⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓ ⣨⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/_ =>/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠷ ⢀⣌⣬⣮⣾⣿⣿⣿⣿⣿⠌ ⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/{/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠰⣿⣿⣿⣿⣿⣿⣿⣿⠷⠁ ⢀⣬⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿*/}/* ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣷⣿⣿⣿⣿⣿⠷⠁ ⢀⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/**/}/*⣿⣿ ⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⠱⠳⠳⠑ ⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢎ ⠱⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿*/ +/*⣿⣿⣿⣿⣿⣿⣿⠌ ⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⡳⡷⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⠈ ⠑⡳⣷⣿⣿⣿⣿⣿⣿*/ +}/*⣿⣿⣿⣿⣿⣿⣯⠈ ⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⠈ ⢀⢈⢈⢈ ⠑⠱⡳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌ ⠑⠳⡷⣿⣿⣿*/ \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..429bbf9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,132 @@ + +pub fn convert_bitmap_to_unicode(w: usize, h: usize, data: Vec) -> Vec> +{ + + const CHARS: [&str; 4] = [ + " ⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿", + "⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿", + "⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿", + "⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿", + ]; + let bitchars = CHARS.iter().flat_map(|t| t.chars()).collect::>(); + + let px = |i: usize, j: usize| if i < w && j < h {data[j * w + i]} else {0}; + + let mut output = vec![]; + + for j in (0..h).step_by(4) + { + let mut line = vec![]; + for i in (0..w).step_by(2) + { + let mut index = 0; + index |= if px(i+0, j+0) < 128 {0} else {1 << 0}; + index |= if px(i+0, j+1) < 128 {0} else {1 << 1}; + index |= if px(i+0, j+2) < 128 {0} else {1 << 2}; + index |= if px(i+0, j+3) < 128 {0} else {1 << 3}; + index |= if px(i+1, j+0) < 128 {0} else {1 << 4}; + index |= if px(i+1, j+1) < 128 {0} else {1 << 5}; + index |= if px(i+1, j+2) < 128 {0} else {1 << 6}; + index |= if px(i+1, j+3) < 128 {0} else {1 << 7}; + + line.push(bitchars[index]); + } + output.push(line); + } + + output +} + + +fn read_jpeg_to_bitmap(file: &str) -> (usize, usize, Vec) +{ + use zune_jpeg::zune_core::{colorspace::ColorSpace, options::DecoderOptions, bytestream::ZCursor}; + let data = std::fs::read(file).unwrap(); + let options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::Luma); + let mut decoder = zune_jpeg::JpegDecoder::new_with_options(ZCursor::new(&data), options); + let pixels = decoder.decode().unwrap(); + let (w, h) = decoder.dimensions().unwrap(); + (w, h, pixels) +} + + +fn main() +{ + match std::env::args().collect::>().as_slice() { + [_, bitmap_file, source_file, output_file] => + { + let (w, h, pixels) = read_jpeg_to_bitmap(&bitmap_file); + + let char_bitmap = convert_bitmap_to_unicode(w, h, pixels); + + let source = std::fs::read_to_string(source_file).unwrap(); + + let max_width = 120; + + let mut modified_lines = vec![]; + let mut buffer = Vec::with_capacity(1024); + let mut row = 0; + + for line in source.lines() + { + buffer.clear(); + buffer.extend(line.chars()); + if buffer.len() < max_width { + let needed = max_width - buffer.len(); + buffer.extend(core::iter::repeat(' ').take(needed)); + } + + let mut i = 0; + for j in 0..buffer.len() + { + if !buffer[j].is_whitespace() + { + if j - i > 3 + { + let bmp_row = &char_bitmap[row]; + for k in i..j { + buffer[k] = bmp_row[k % bmp_row.len()]; + } + buffer[i ] = '/'; + buffer[i+1] = '*'; + buffer[j-1] = '/'; + buffer[j-2] = '*'; + } + + i = j + 1; + } + } + + let j = buffer.len(); + if j - i > 3 + { + let bmp_row = &char_bitmap[row]; + for k in i..j { + buffer[k] = bmp_row[k % bmp_row.len()]; + } + buffer[i ] = '/'; + buffer[i+1] = '*'; + buffer[j-1] = '/'; + buffer[j-2] = '*'; + } + + modified_lines.push(buffer.iter().collect::()); + row += 1; + } + + let new_source = modified_lines.join("\n"); + + println!("{new_source}"); + + std::fs::write(output_file, new_source).unwrap(); + } + [path] => + { + println!("usage: {path} art.jpg input_src output_src"); + } + _ => + { + } + } + +} diff --git a/test_image.jpg b/test_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51a47d0eadfeeaa839cb0cf65136216f5777d559 GIT binary patch literal 580864 zcmeFad0Z1ow?Ev7f-8(GA_6KZD*L_@6$KFiWyc5+LkI{-1QJk~B%_QnBLXS{B0@y= zHL^nxGH#%Pge^oiQBffYi%Oa$A<3`7ah7|Z=Xc+E-}gR$(fOph>eQ*KQ>Ut{t55Z} zOZ-~=7Wm<)wXHQEAt3=IK|etJPF~j^k3VOsrG*XE^zp@=L1`j!7_IX@=d^S*wY30q z*!gol$Uqc++Zhx(0BfN-QAbzZ7T{~4>TY1KZGX-RX2zySO>R5&gqaGQ>%p(>PNh_9ci(;@5Mvx7nws=vz}9v-e4uBV9$L2K!ln3!m3 z>uTxhYCs$sp%<`tpYs~nP!*`O1u+6V{z&$>>IQf$)D|je<+g>Q4xvJkApz&`0XXco z`J#Q!;0SmNRRSTv*A%5=Y^djFh}1C9G1k}6(ed@w@ImS8XdurR80Z_C=oz2!)lpr! z?e`*4=L7zf^>2mF$9yk#+cxw0ps5uu2p8fEX&hy#uWO=jVrZmmVqmWIU*n+MzwsXr zIFAbQI23?EVM8HVEe-UwwSQ;-uTg(b01CQ3=DWD1j=9!iFRwF*J`;8BO5zoo9Wwy}n` zk%o@Gi;lLbj*h9m!AbM^(etlN-_zOSd;|P0{155=!t_TvXu$OK!TbDADgVm$J?(<5 zxDXd;e6>6Td+!z_&J=X^p!QS&8OsD3YE zp`EvxFNkIufDOg_V38=>LzW9;Khn=c&&0<^UqjDV&*$6NZ(@Yf(?A&-8KO+|kSISB zs2BgYv`}k&&(Rl$BtWAz9?J3C9T6fxH~F*N?S)y|NnMh`=f|IGyBi<6kp^Y z?R<_960~r;_eE-86y421?ao!=YU7isE;3&Hr{EdwwtocDk=7$Y3GBO+H z9hnW^lC1rIl7aX)VC`}s5V$8Pu>)ALRzh;Egm?g|_Dbn_}>vWbKIN`H? zNAN{msSP(WN)M{+-01Y^jGlhTrFJXnT{oRSzx#p=HQ02&ENb_m1Q*}Kk2CRxaviSk zQD4h{e$q)8nzUBEm36ry@oCowUUua(=10)YFYHQEPE}*~rzs;FcXW7ka&C1KYj}Ds zuw)4&?a~FAq@|V_EQqjOXWddrg5VwNm+4--v0+|&_l7jo&QmGeeqsQ#B- zQu6{x?>2bc0SS>Q=X==I5RZEQhY0^(0@Xi75cdMBB^SzE3%~$NO?O9*@+p6A8ai}@ z6iCA{`%f&p*!4r7-q_7<3|JKrNwl+UN6#$_+}Y05wk#E%84(^Fbh~zEpev#Zvn{6R zNp}1T!EVdxpv*A`+Cz6Sz}EM!Zr4?21=Hk?Joi(CxqNOIaI=O-c?b}w3t_#}!j<)K zbt+pFn|_m?*2RzaG$E=;XV8_oM$Xx{g$T_K83PxIYG&c~l1jQ?8I?eyOj4$?FS+2l zJ2|cS``OZ~6yrGc*n6#siDJOt6thVT^ajah*X31RiAbqcupslu{zBD!vtaGpqodYc zdNf=YEzbI|VQ6Ys$(!MiA30+)plP8|w*dB*Zf7&n_JxmQwpIhB*-_4ey((f9dXYrcF(@MsF)-WS(P)iue0jdVj|0nXVS5tT9M^DmnBJW7jFw|3 zZ>$}wJnB%-O1U(gjMuy^;A^S&Aq5lp>RA zmiLsZqMCPVY^g`{W;?pkAgXR^XKu!br%)w};C($POZ0+sU>4?H78BFD$$Gy)>o~jG ztcQzag-(r!Pa^J@3pJQ7E$kHJs`Yax-(Ep5OX|kzk=l;gp5g4&{6KGE1(8Ced~s#* z?dXS;654h7bmp7nPSaEw89jw0QM6Aa@mS$k$&x3?Ks4=Y>44X?x4_F=I74SAw$^rX zUp!)PyN3s(x+4tN7!zH)erUgu^vQKK0rVIXD1CbWK|r=e!rtC=Mi;yr6a&VzYUZfj znhl7U&cWoaQ=cEjM_(E24yqjQqj6z2h6q4pw}}V9zHZQ+CSFN zZ4?Q+D@3=~%~swgmgkJYPaw zVW)o}+$%+WFv{LVr$xB_YjBuXGFBj*7FfVO>t^QiTFcu)%Y#q#o68pMsvP36jOp!M zjmUZ_B)yZz&eVyTWuQmKd1AoEl~7iZ^JxXYJzAs_;cZEFtJYJ%bluWlsIeeB|kQXy89WipiyPnlyP zb93=?clhb5`92JO@h{wh=BE#szsB6MfH%Cjc-5j?H=zFW5!EeTO zYsR}fu`ds(te4w{JP~uZkuICJD*C>5P)_W4*sF9(J1>Aws>D&dn~D=|bOo1>*Z$;$F;C;xiM@;i=TsO(B*^cE6T7 z(aA?`9E&Uotlw8wyk=f=a5}tJP%M-iA&jr;~@Te;s=#m=!g!CTl;1%7i zitx@XEaQ*oixM=cWVZ51C%Y(SjD6lqnIi@caO5#9?3!rR{Eu7W%ewVHAUd^QBShG3s}9vtve#f$fZXPSGwk?jSS-=Q^+oBscT=u> z>v(%nlrX+u47kO>4u}D{!24hedX#H%VuIa6Kept!NYu3tD?|l6#q)#>an%*fLt*Rs9W)PnPzK(JY z$ybl2UgWq9I7M8ZDbJEa8x(}z{f~QUf^P?S& zsfI&ixLgPF@zPFLat4|jjdG+7cJQx8>FDvXno@o^c>Zm#T?{m{f6k4VF&%TiIW^%h z&d6xJtWt3;A%dI%S}1ptVt1J;dqikr5bv9_PYV%GE(nffs^y)qvzxd;Jj2y2EfVgc z7e&B@^h}{_TTYfkndz1AV{9*@0>dIB{>EYA+2%Hn{vVOmYg4opQ7Q7uZ%6u2lmJmc zdVE2-CRItG3?^((L*&1n-qge5lSlUD5A`YPt?k2A%PR2osC1N@r`Ing6+=F6{m_FB zkzXR>md(ssIO;!R`5Bk11x}-Gjx-9{fa9 znr4yVTOI0@@P40KQ{PqJ#{qM*SMariU5uo(ORww5#K?3-ZVfsUm^x7Kyq(Td`AQ# z)7BwJ$)}k^ciFpfQ~T7lR8y1;wlDCvf`Ts(DC7yc>S*^T8iOGQuDa-IPe#NuDa94Y zYGy-8CF(=`=XY@f7}s)p&*IoM{KctY5h=G%)j&2-3%~t-y z@RR%3@h8CIsx4c(Co%`eJiOcs@N=TP=^-EI7!a+zqsZL5{8D3kn4w*2eXYxYV=j^% zNT(FeQtUeU@=90RUln%|;xaqSBAz9|-S%2|w`RZ($2Af#<%VLQ&@s>C_IOp2Fl~l9 zMgCa`%i!KsaXK!-Wod+34*W>vJ&BsEX~`WHzVO3riI$ zQ_)%YI}sR|yF8}S7w>&jH-h5IS$#fCtCvu?g*H}HU-iKUQJE+r(xKbsqoSf<@DM)i z%zIC=%Zpbp3mOvICP%B1hAh7tG|)6k>b{JI3dt2luf;%{82A}1X$0(AV17Y^#pjuh30G6IB+;Y?^s=cAS#*c8cEG-_S=xKFss(Sg% zq{dCRPBq)|-AK#7n&`|`G0+jYo_J=Yis=0^%!p|>?L%N0Wf4r(gDY4!PG9w& zb}VYf6z*u27XzonfSuRb>Zp_6bozbBa)RPRlbKa~`gi92^WQzgM5M}%9$I9`SrfNQ(9=cM)N1$I;Gb0tm z05tLb#Hrk+Z`trneFTO$7qpSEwYyEQSNqch22)8zI({mjjiGbTf;gNDJ@*=|n9iB- z0r#xBu{HdzQKa{F9fB6SrCKeY)@asOMf0c5R*Qkl(0J_h^vUDL+-ZF4JsUUn zX5pE;Sjwdi84b5#Va5b#q{}!lqfv;ujcDOlsrNnz!X4w&`d3-L!ntu258eoD{Dd@8 z>tu(W38D-WR|=0p^OJSX%=FZ7SN>Rsi1vO<8Er+ACXo>d9|x7Pq|+l0`ms>QKWM_gsj|r8Qwo=w+iMGp+t`79qXfJ5>!S2CUcxWRKW5ele2| zv#EH`qZAst#`qa4P+ydGW1cs^Di2j~(<3X$Bv(datm-7yOM`YFC;H9HT?Ke>4zTu!TyAag~)c|4-dj%ysjqk;awm>pH< z)DqubVV9U58fK`3Ugz{JGU25T@yVqBr)I+KLc~W&jopuBE*oKLgq)Q)egU2 z^FnTYt9PY}gJW0Bqd`r=pIdSu41J0{!@KdPpQHC8I0)IOVQHhR0t z*pgn+bB!x6ylj`Zx+H#zl#O;U0|y49#qwa__-kZQ3S zQEU>V!BO1wiAOCu(BWXci=IK<4b{C?-;9UDvDIlW>+LMk@9Y}Ty(>e%?Ct0j?#a2G z2AABDDqS!c^RxPo?#YoSby5?EB|M7VAiYNnY{><&B@|Z4OMdNb#4jzaS)$6gksB%3 zw(>=-j7)Yp&k~x$kfw09$I1o~Ol*o6FfvV7OnEeHky@(AZ!|hm3D%9t^flD8KDbXM z2{U=*OkT$TM1XPga^OU zJw6EankI5T+1AK@q+Xh97tcDXtBZZbo-hKp8dY91@;V$;b>&29H!)smm?;Lr$Toas zBxGuGKK-$?BO+bPj{mUlv)WTG0SR8!)FdRau6w#I6V(ZANUc0IqJDXo7^o5DPBvt| zb98OY)GH#K%I(2AGDX#q55Dw_mkm~y&TM?^;#JpC(svdNdfg1WQ_b@?zS2MUV`Ri& zmM8;!-ai^cK=(Wd4m29_jO$KI&#|arCEF)Oq!+58!pPajM{;Egi8%HJ)@j&g`nqNs zCfTHfe4MU8I6qs z>A7LHGTSj1oIBP~dKvtA2;N01AB@2&@GZ7!J7boO)$Jbc9qTgWkS@bvmLF5WGX?zU zW6)ip)(DnM^kvU>`|_etSk5$-#4#T}Mb5!qz;S^m() z#8?}qv;9V5U8tRunwPWYN~0 zZP-J&u*tMAWM5fs_Y{oxCbysn*+)rc%W!F{Eu+1r48A0*$IifG6k z_vYV-KFxu7SeEgMPJWIvA!!h|)@P*NR-=8QYYb-Q5-LgP5l=C&p#bd}<}HihrYNJa zVc|W2jHhgt?&vjAI&0;mI+#yLte?dcP(3McM?}|e-Zac1{Fq*x)@45+YqX?_3Fchw zRc~z0a;)3p#ot<2NaZ2G!Y^Xr$v&a25N5`il(L*CwBmeB{D>TSZA&`r{=n;E0^e9j z;;KROZeFCr{3$1dUg4y68%i5!l5s499J#+6XDV?Nh-*+@>(QKMl z;pq?i{nlep@~a;R_LA*h5H@tQG}gXpJSo^qpN;?gVs8fbt?(p2we72yYf61!-UqXM zW8Poq}-bM=>|+%svhDn zBCw!9Nl?lWs%FoE=&#-$j2g83*b99!IJ%#|Yi9wW2}0_9;QZ6!{{5<32ny zkp)>W%?zvah`vuz%#*`)gQ*=DS}FoNaiWNXwioV763SMx#K7`mAHu`dT>I`GR^anS zPV}y8{2E!V(iLm|=(7TWJm0)OVoKDKAqFyP#lZc{*{;#XXCrhM9a=Ke^edY~bk1|X zY(JZEW$K6NR|Y!8yucjpm#R~Z)x5!1z7gr^PjAuToOnJX1~h-oa8xKljd5;u8S<-L z=6+{QoV!8^N zh0sdN?b9Z)O|p^o$`$Mzd@ZK1A$Laq)@yDBGZB2E+tly>px<=a=2qO~u~(01MdnGR z^tbA-A_vFBz>;WiPhSFa`~|mFy@j9hi+>{<1a?&#_F^l?2hasm5R3FEG0FLiDm)i@ zq}am|+O3PL8c!o2Gr-g_p<0SRp&0AsN++Rvwhp#M&|irG6PuCt;2{1ZMEBje8y9}V zb<5;mQ%1v!l-q|)>WZ4M3UJp8CL1FV_sSULY%dZ$A2Au=Ac3mjMUbki2?);!x+_t* z`{9MqH;;$B4?AR$OLz|kJQBV-upzuam5-WM{eys3@~OpC#W+Zw;gR0;Lw};!?a9Q zD^%_(>q~0tX7ruM@au0|sENw)MUj)CxE~az&Tf`**6JxIgir9~#lQ+~gk^HxO^Ud4 zw<}r{Mm*CrGP_xxKxhe#^;0YBJ6v4f!YjsLdXOcR@!%W&>%q^I)(LwMJ9o#j;T@jK z_h&n@2Q+5Vue?JBto16$u=X&xThlzHuyZhN|{G{!mwG|yv5wWiQ{=3lp z;?@?w;}@XSHSNga`wV+V_LPn&dPbGS);k{@OuHg|l>dl=MQ4DI`SN#krV~hp8^hg+ zMP-AZxK*EI!<0J(upYWK!@bkiKE6A#|?jv!m@2K^3CyS(EYF=Jye)BRJVtMr+T zw`u`ls=yrSu|lFWGaKF~aTDlWdUXr#I?>KYhHZ$N5YM zJi(dfeK>QZR+L9B5CaVAY+xzJ$QK_ds^C3TyZwocP0Kkg>aJqk*fm}F1Qu~` z%GZhU86QDrZ*pfAnWv{*W}3=&{|Mh2*hr%q_0poI;b zCMp&;qJZ+KvSf)qInJFNA(g#ew;HZ3Rjg|!vC_T{0+AdQ*Ag%Ocw+24k{CLMn^cjc<4Ud88 zqqz1m0R>K(`q7>~qdH^t(N`GAP7BO_E38aIlz?0JH-E-Sc0MVM9f-fna`9%kU7i#WO2)MzYe2+0fSZz(LxD=W!`7s{XzXMOpehVLtjg=gjd(x)XdT&2be8@(-_A2WMWp>%XKQmqQ+#Ks<*RtRx2xl_x-D7lM+U0VJ^84H z>Y06FKyQ`_%dgGkN_QK5YDn;Q-CUbA?4eMhZBfCSQ{PA7O(D;8@?p-r)WPe;L?3~T z1C=x3!KcUdPZS8HN^!;Zu?ladgI*Ar@g0T?9JCZCiW6vo3HXQJxry;$rrxHDmn_SN zgt^&B%a@IZe~X|(BXl+G6%{oO^@jpmdxw-?z0qAtvCbO$gqHA6XuN7=dChxI?uVhz zpT^7CEcztddc!cm`U8k?dKgCsGqY$#q(r!#+Q#S;uGM;)g0P5&L_=R|qm4>g6(>hIW3mq;`MZEM3P{+gCVH81tO+f=(Tv$j zi=-bO2V*ddFmxS`^O`qG&YR#Rih=B6XtAuTicwe(<9geSjRpzM@sG>UT0Vc7>cf;W zu-3b+tbDaXD>ZXhhYc4`14lQV^M zC8P@)I?JG|r&B058M(o-dTTGK6w%JdFiEX^w)ftgfy2j0oDpyz0e%Ns*Qg>TpeL_A z&zIzG(qV`DfU*T|G5mX9e(l;`jH+wxn5(N&?nL@w%Ti%nG4Qs-8J#_hM8mr+OW)JG zsT}COp1D3(`ck`A2BUI{{FoVt%k6-!aWN3%VoJb+%K3_Vxx7zw)1s}JiC|PtSJ=n; zx*WQ7>|pM**JG(%GGD<0=HA5%Z>T+VpAL+q#Ul|MI zc+Ns^47i_Ye94AQ(zjlN>_=UgXYA>rNH5GrlUL|oPssEz6sar*Fk}OC&dnPi2&q_p zWinVAj~lbB^dGs+thnJVqYqu3=n|Oa%R-RoID>Gbe@@TIwSCk$GUy!|;U~E)950F) zIb9{GoDjV6gQf6Icf)kA00w&POTtPSx;s861#%1JxM4PqVavelpIAx$#M+)$O#^(> z(N^;7ul1sAQYB^N7A@Ky*WEwo5Y>gVQ0BT@qwizSK^XTO;LD9ze7oP&C-k+yIl~SSwp`@E;IegB)--k9^|wctg_b33sJw3>Xv|2d)cXN>3`5tV5*k3&F$*|DC^p%^sEiO*d}wn(yJfDU(fpL&8dZ+v zuqsoV;nhlw9b8D-tvBz)HElxpY4zR_m3Id)*oszpJ+-&!FwpFZc}icbHLSSvfzVWK zn#nhX9nA!zi%#=!`N=%x!X6t1t;`SCPSHK25U0z#fZ%fk&e&b-9C|bnf|9XU$ZcsyZCgnNp-7F+sqmBOdm=ZZ% z-z{fuYN33RQ4YsWd@2%dsqPAFs^-EFCDp4u(XJzyP?!NDxvKXRxv0XjpbfgBzgz_4 z&GHq6cDd%xKQ#%rjF9shJ)IrvW|Npaa%Z0y2$9nO!?zCeu!XN~TR zU)NTF5U-h74|n14@Hm5}2mW zrS+C+7p=U!B`@;E46dr7Y7GYHV;VxeGMMe$kkIU=bIABFrX@HQDeCI13Bs50B*0X` zn^F0Cg3}kCdy>IVMa|A23wTNG7rSU?fls-{Qxr!zt#zxc9X!?ur4Adg!t=3^^$l7} z-a)kCY)+F@<0`wqK+Rg{q!8XQDIP{r-A$*YCR%xcxub6~p{1Z7B2Ud;Q$-XKXmKLsHrUTT0=_vSR}N7&ou^l zsoq=F>&|aPJ?Iuz5mS|V)p$kZh9)NeaEZWQ3{VXHItI&m@p&^+xhXd%*>EqsQTPNd zQeFTJ31Z-ir%=yqy&Bi*++j@Ns$6%HEK@BgK%mukws)|iSD31+TT+gKTDv2HoCyjy zl$}!qqe{^Dg7PQ0>P!~dn`dXI!7--XUlV$JAXTj%G##`;u5%htkd*qw(@bUlMA{^0 zUrqHytZC?*=<~X;I_#5aQG|k!K2wp(j7Ww*;*dSd6!;DWvdr^t&uW0mb(87c zBJyw_hlI{48!Lv^1{;d-EIgdv?4_nSW0Gb|?9%rY=eIun7?#r@kUEi2p`9_oWQcdK2 z7=bPnRYi9Z5wn!E5n}4-pkE15%dwr}IoQ$ABXSnft7ix38PGd!E8|64Ln40=QO3yU z!{AdkbJ@@88khn*9(0o$p`R85bxQGE@B2ps`>hcN`DtMErs%#-{`zM`hdc0xT>%8g zx?Rlj@X6RF;uK7zCfvc~B!iln%n({3=8177{2Fxq$$Mw6N%9q(>X-6#?g`YPCAxle zPP9gHb0M=x31snzsSz02^qHxsb_g~IQ<*%vy}+hRXfy_`c94U_z-|#k^i!#2F=MWU z13gA|2&_nboTrBx=Hq%PRwJY)VH6)xMb={39_3SijfK`>Wex9y(9&jR9A3Q2RixzP znv7Q~s4DBm)T@@aJ!mMVe32s?)vp`A!#C=Vt4;Vd_C}YZGX^r3+Q0G7t8L-2Uu295 zVfo?E`#t3dKI|}@jesm>X=!rp0wqSJCxa?*BPzf?A}UF#oda{M8Rbuq)nuPc4>a}D zBVA$4z8D{@YmbFG?=9F9VZ2C{N9lu_Hfe6_>bZs}YrTE^+Rg}r+MarYC+EuqvUxAZ zX#+hU9@Ah7ND261}ndNoBoXN2wj)mdAq~PW=?$rEc@%lgQABI&suawp?w z>%l?Ftk1(^WOKQL6Ye5BNUG!47711Ttc6x&o9RyS5DttQ;VTtZ5pzh7%$nw)NoZg_E@Olb zJ+%lNd+6hjU-PTke7XyfY{wMrqM!wknY~xJrAN4Glw3e+?h`6Z2XYI@b-lgnHTHj}@8U%5&*bkE2jdQmEc2YN9Mf(ja`c({slbX2D3tc8Pw?IbWfQpK0 zj?Wn|zA)!W7vGye#c@j3b@y_LL$w5l)mNi#k)djosMRa1g00GbZ&0n5=hdP2rZpo} zs?kik;CRbKML!;w;X3GFJ}BCFoK2$4J!%2N`J`H&h}EDPAO;dFU-22#Iy8^oE(W@V zzU4yM*;-sa^t5Q!Y1vuMOrxXlq}M$1*ltFyKoxr3p_Na`wLKCXOe$&zSt?n)-aro7 zy{yNiYSYB#pQY8?stI*oR5Gox#RAup(l;ec9qk?y$Yu*7&A}3G`M0UB7@|(t#3kU5) zwhd>9mRLS{+6Q{*=n;<@HvajM6zGdofbl_F`=#@^3;>Yc3gI@EK)(grt_9i;)~mn% zy1T}$_rYC>j0d^b!{_59$G*k=j^9}F{k)KF_d=Y^g1g|regeMbxMm?ZU)J>nPWeB= zN(;G8E`(PsxR4|9E!E0}Fa$xE=TZHJ=2*FayqJ$zvXBy7;5hv@6vwL$?^rtye=TUEZP6<|GSozAS$qcT=~YkWj-kB3_0KGJ0Aq*Q861gLmpY+ z3=jnP07wV~q5++;fG>0o2mFBm01u!bj_=@)`DEXZztHA$`2%C~J^o)N`d!?49xNd! z2s+JIObYt?7}ht`@yuBy6#6}5CnR163N7ft1$S;+5Dtrm!VAYSlpp@D;e&V_=3Dri z7*1&a-{Ti5C>0tMfJBA51sw~8l1u!poMj7f5P2Q+mtF|i9{Nk((&!Kz;oRRyQn-)+ z=v#3pECBMoMH!dF9xhN(zbkiM`G2R_hoVt`qe%G#;az;tf1}ADQBXS6dAx1t5f}So zXK=Wn`3#qTC;yFkg+DGN;y_RU`n#rNzg7OocQTYx+85>LLkPk{-W6e}5d6Pjcl%EM zJNv3L=!K8T{YANJzvX|>=8p&{3E+Uk&g*&w9(T@>fDc9ewd1S|f;!TFqpm)K!$TeF zztLAgP3-?)*%z+PJ@W+ttD(OH?DK;E+jX~g!4F}l7P#gSaNj!gx`psOKcM{-a^{tI z5Bdi}-nRho9P&dLv&|4fY!Oqoh$;ItwTLNO#FQ;!$`&zYim8<6i^O<~0x@4K8*zJLo(G zAQ0A)C6a&HItN&>QhGVGJ&xoO2-xuy@Pl^9k(68_xooNQQYq@$PeV4v7^7Cec(5QEZo^*WK z?SfCpEbn|Te=Dovu&eJD)jig3?tVXih059Z=jJ_-;ueni;^o%vC>dn+y3e>vCO=v2As&sX-nCvaX-@??-h zt0!E(lBZbo;NA2F_?e{sEoYB#9^4o+CLT>pRE~=>6x7~tW9#nI-MV6ht%YOyPZxrp zJ+)VQUJ)4n>`YFQigTthe?V1nzp>;Shl^)x?)E2B18K#fu=baCrxANZN`!UN?_!r~ z-Rtwb^{k6qRB`L(l1BXMVqQoMKK$%?UGERf`$?Y$nd#t98ByRK(M!iicB-G-HpLJc zJ?`zgUbI#6-rH(c*j_hR+T@X&3ETa*$>7!i$zxta`;^*(KH3lItSodpUQ_Y>qgP1A zr7{a>CoGFL+D5m$8rFrDZ1u##u7s`;lRf7sll$+a{AO{(M1sk(SFbP^_vEA^p@PY ztdw2V8Hb!W@nUwwWZ?6A>s0?oA&M4H7zM^0m&QMH1`3R1EC8$CD&4!SJ=`6X>*q2SQ@HGmII>yhr6$F4WC*V$Uw zsvfBBv-U1>P5EfcDZS@|%OpM~dbjjlomg+AvNB*}6&ZCx!J{dncf*EBy3FZYvJtNL zRHhGo%Kw~oH2A!ozv@oDzcfN2_0c+3<|%je=$lEmbDGsoGWI9xSFE4eGqOqg7rV=; zmnKpzbpKiI*Ljtjkt>okpzn^29La6ZJEstH z?9z=Xh5aM0oXq!lg`P6z-qzFFz+>wuxq<^HS+UacwTUjzuLJ}qw`3~^#cM1Jdt+R( zoT~a;{!)@h8zAbfv*1Qv-Iw?r`UvUZxpr-e_c+O%I*Kr%M0-OJK5`(pL;=oP1%{o^hlem=d# za{m&G-$o?8KlL?7X}1KSmVQ_Z?SFC;^|&+t+yzAm>(LeOOLkSB>oN{6X+FBS;JGm4 z$UZmNkLzE)w}cXJkwl`~hTMI2wS3qRm-+5qOikCjc414;s;eDWFYk2<828yMIIpy2 z*_(R9Gp^a8F2$y|%whJotK2rk{~&8MgFHa-@q8I?Q0DR5N?w~hA`|YEy8cHjSEJ(k zGlve{P3E#q{@2|^ARe37)yG(O;J z*kfz_)%mijh$i74ob>9%GeeyO)`8N#UekSvIZu9hzOqeQu08(U*vmChH42lO+Yjz8 z&{%TkzGZLupt;R&A+qT|wY}~tRZ8zoy1O)YvhDOZ@)0ehGi{mGd#8}MeS|w#r7NE8 zM&{4tm_>tImL(2)!aR#yb`}X7UJ=ileA&fJxJLz_G#hw;rfcednK{(;6MmU8^gV|+ zSNew1doREGxqELp`=yB(c7`E6@!MK2-I>bn-7(f%$mt4h@NKP1 z^KhKHb8@S2NyW;G_4*&3HFI|u%j&7Yk1`5eoW+1<)DwTzoHg$h&rTi};@6D5PI=g2 zlyEU}Wxc_8cxH#I-A!`!*01qjhYnz~x9{_@ryP{|=|WiSXZr_&a<>$M>-`;y1WLf2 zDC`FC>!+rqpRiqZ9@VhRrWbqb%h&pLI#Y z?2E2Vs%z^#@rbzQqsrV75%K`mkXp$?8RaLv&Kg(Kcv!&;7>%+cw+D;;1Kk}g3!UUOE-zQhj^%E4`6JDh)s+fjA> zXW5;x(h9We4Rr@ky6H-V-rHKAH+51IyLsZMZBX7-pWwZYDF-{q2l1=YXt$CCiRs=C z>FN4EaG#G4I9bR<4Ik*m=x=h1pNopIEF^H}5ks^HFtghz81 z+qPng@z}}Mbmf6(q_>BoLS7c;A2<>x1}yd7uM3^4SUKIK z(QHq}5qd1IAIyASvoq_L-Dp)*+{+tMUf^UYJA$>M6jN@VNxr1q21hBveKdTbqk zP~teblVmDI?xB_K3!4mB#n3yAw2WBU+^1Dp88Ij==Zwz_#9JuKEWI|Ap#p=k_DkFk z%By+XnBHYc!Y{FPyg1o*s^q1TWMN(T)9gD5M?G?^Yi^T5`|HhemJ>&RTz4yKB3P2K z|7rNDFZpeVbMXPE^KC4*tlafX^r6!B#=a~s;INEs!mjoG37#Sf8Q7%w4x7rzhb#eysVehs%iVZ7oRICTJU9zf@{ip>$7ufEkD+H;%eoOPdHtt1fLku z{~>```%t?*&@Q{BaA)?)rifqVZD()XyA>8%wLU7gw;<eVcThpXv>$|#+mVL;( zcC$x%e=YsUmEZCd+p-YNagntfcu#^)<6j>C0cKdS|JB9BfB<^JkGt3xUdi-)-PyN=Ze_qq{ z)TgGsD^&LvJw#vw8gLxulUE5R^3A_S%W_cIm(q^2+LN zp4ai>K*Ki)mO<5Ro$5{g`F6oJ_xDe#{vQCnKtjLr9ZyXGmEl|H(=|h$p%F2s$&l%B$C?K`q@Mww zO$7Z$+lpN|DSl=LDChz3&}|-a6m)kG+V^Kcill`c`RG51Y$W7pF{;%VkYlM*UP=Z& z@z7U|_1bG|c4&1fC0Zh0i!};Mjh`@d0N=F-u|nqCWz=^+Wgt6Irm1RnWh@M=d6JJq z?mZ93KrAket*KLFxFRsLge;}TmVy+81A+)WK^~e7?$BCNpw^msZJhIroM;&f=)B!2 z8zHz>x|QumtW%|O`<8{EpUXf~A8hj+A3Xr-?eXB2wZtC8D*Uw=ThpkCF866pN^#UE zd$Z8{j)8t|ou-jF4k^e>WB!)=q>7eT@dpXFipz<7p z>7X~AfEHA{cZU1E@0OC5C)cAk&oJmzgc48Zpd>b(v!;tC8qhTKd>+y%t1nI$Kv&@E?eM+)^V zwc=iNZTQRjt-_@q`7)sFl&Qb{RrA0-3V^U!j74&!F)ZPV(>X?O%Hp*jW&`Z)W*?Q>x+ z%L#Kil|{HC%4MweN*`>bpN3F01`^1a{Imhlqbm;ZJQZmyP?t{(}4&7 z00o3Le>CVnyP1A92H$n2mDHeubD$Glvb(kWD}@{Bu=WJj+GQg?C!B%#t3bSahd=AJ z=La@_1$?e3bv|6G?VxSiu znA%tE1rdcgk3^3>07~3D`fW;ViPNU7=@J}L-*v_1OHnx_pIroBSgkoR@{qHP=rS$Z zEA>aygc1qx#)8UlpTdpby;sFD)U|ENQ{_#V+YCpF*)BfnkFwG|=fs}`jHvV)2Au4> z?DMnu64=OgY-((0F50YSp1i9qH`kw+*@oHi4K_Ms%;cV==q%-8qSQuys~-R)b;p3v zR_-V_O$ceqQ!=?(WhAVF;&cGVw#SRZQl5>6w`czCvL#m3h4d%xHT=$iN?$dFRO)IR zzE8s5-#Y9uCB^rxI& z0#cAqj)8o;LwLlj@g=)6?j_Awrbb$rqsHdwhC#=uMnIW_Fcv181NPS)b0A~sDSs3ui&@=A|JTL6`1N$cnW;U&c z%M749Ual7O zZG*M-W@?u!fk~G$yyj*GeR1}e{h!A`Ah%C?ZynURrQCNla!mQN9V&iQhYFOl{D+_& z27}LT_Ojr=Dy_$f4Q>^jpCAXBB=i7zlh9}kzhj5d{JD3XG~MUl2vTTvSt)U)Eu!4Y z$~@4*NCl=(fpp#-cjwvQix>A-2N0=mpnlA83^)VJx|oX>~M6uFXo5NT&Cm(OLWI9!VZL05`t- z`*H3y+dk>Jt1e8RK0=+6`-;g@iSQnPcmbe~=+mF9P5@;^O7hTO{>c6XZoV-${)@KM zb_-0pqWwmC(Ud}pj2B;5uP8W3^HP#MbPXT1TXAOWrq)rm$8YI^9U6m9ZWT3;K17Ta zA5|#jMER0VgMi{kaGSO*S0T3c9epRyz-R(zZGRO|Y@Mr-w^aIuYS$@J3KFiZ#|PR` z`1pME0OszE{ft; za8=3*RKGu}GJo+E_lW9{c}G%k48gM-MPO|0flaWs^3;n(x9IWG)iRkGpp>C080S_# z(vPl#ad2D|=n);MRVN}mW)e!);;;bFP#!(IV=bMNs7SCjp-G=vY!KoaZ~)Jtb$xjc z_6N1=jRzOmrP@osoK5asOK*1_)>NOXm*N%_NlHhLQ`Z^`)M?I1il^Q7m5!wP=pkMA zZ4qOynLr+=KnS~iYP8? zxGj|}#bBIx4^yCKPor(wMvfM?S&k|9Hr?*8Tgn$DxgJY6a+yz733!9{R=$V*(d2Xm zWl*V>Z6mKLN>k!=6qB^qj;dC`?S$uH%tGhCmSDyU>igt$Pxn*ymH21^jem7&msQU$ z?7J$8n^LGgU6T9C$tow`l$5p2goy|o$s^uIN6$cE z5c_p#MHmMu@z7OH(M}8P{wMZ|r)W=rkFEw*s1FqNO7Y>Jet~s3gxD*$XRoS;+}>2j z7@bdfNo`Ibj`;xK5%2ZTMiCv8MVX8dgMvMD7ss-jw7$2)72guXyei9GuRcOj(~dYu zg5r;X{{YKBk?Wv8TPeIW4bQZrR%tVk`!X5|NkYN#8V*y7J|At(?c1u2sat@DSeYG2 z$xeArIvOI;Db5^H2Oq#f^B#a)K z4(Eq0*sg5;=h5%Geqx%JN~kv_l9gjTssyLtMn}&;&YTZ%A8Bu{*U_(AYM|S!)FC$S zC{{`oN3@gg3dqn|H?63(x^E)e3ky$}&VVKMyzp@D$Z;|KGN)41iapJemjXS6xK2ms zk@#pUt+%xfreX?XoM+QOR(_7Q+f1kN8DFmbRQD`d?>6GG&=tDS1NG1s>XYp@pR2Yo z5InRMUyECXEWITOQ5^{UvU=W*e)P$bF`6KtqxohDqbAH_oW<(`DiYc z8ZXu9>CZq0gOc4x($zShT=dXV{x4^^&f48?H0LVQZ_ea7@FkTG=b%~*-Ig73<#(AS zYRS)!Q=o$@3k#Z}51G(xY=r?(0G~Yp4eV}yqSqUnW}0(_E;(~YM>qCK!oMu&8dqr$ zmhFewN7+k@3HSnWpsajzFw}=??6{nzcJ)V@C(M0O-2#(wHs2=XRY)KHd6+-?`>=Ck|*l_&EW3*UQOuq|p_ikzoHLJ&yF z@z4pL*UmK)w7X+fs6(C;SFI^=X-#u=PC*J^$Y($UZ|&ESCaCJyF-uz3O4e1?M4Xaz zAFTW4Ooswi;aEOe2`1eQ$WkW5Td|){RJ|3_+K0?&It!-b+={IP)9UxdUR*S%`iTfPxVqbkt9O^XyP+hU`nr+)^bMu4 zw;~*x<6YpuePhSppq17zqCNT!XLB9opgISb&{EzkC@j}3JBphjkm6sV&PYKXD*C&G zerXy7rQW(qV$~+b4d5a}qZshQ)HDzUZa;B7W5}HbA`(=fk>+#~j?mM>U27@OFptsK zv{gmnI_9~%j#bs}rdUgu>ZCN*armo1S~l&qGi|MB&TpZe2d56->!!^~zK~T>$F3zK_LzoqtK0v)iFXZr+(G zPNpSgrH3N(9FU$t)O)lSYlE&1Y#t75q|&JM6;>jcXqz|xyuW0zG zWCEkm03ELE+@Gz5peBZe{Td}tVQZ$m8^&}Wj272?k(2?*5ItAn1 zc`rR#A;pvJ9Fymu2h1OxgY6xOS?)QABobm<>4%OI87r!inYhlqmih1G~4p zLB>rnvWde5BLpi!u&Qwd8Rv>Vy^?+U4l{DNiT#U1b;#4OvV-jfeUXm30UyRU6}JxS zZk)(Y#ft;M7#2~>7eKeUiegJllpwkm5w!LO@6gO=pQ zS#4-Opp6BS;Qs)$uZZ3ht~j4my{Ngt+yWr0|MIk2Xd4t@F!Cg`b`?MY2!5?eUX1b?IvV6{`>)vKK` zfn74VLf4L=D&$cA0G~hwE_nX{R;|9?KKal|JS@Wc&Dy}n+I=bfPBadw!wmrz?#$aX zG$WM|Eed3CoOp7^MuVuhC!(E4kuaPF+ETwQ08{PO->LSN$kbuMoKY&{o~Xcub?$-o zzd|$%@wqi)Qn(xeSqVP64tXdlP*17Gf==4Y7|(g5+~lZ_Edvww1aLEJY_7?{;zHrK z+j{7(Hl$l!^B{;VAGaq5@1MGSx_=IUqSzaL%WeI7YD$WaGSX#?Orb8tGeb?l@pKGCGI_O7+LT$oL%vow@A#9p_7SEU1k<)6JBvwWJiR5#UCEMfR-r zH_fNjr*GE5+x_BPCCbGeq3rpdNPS)QD9Qg;Unkt+~qUP9v2_Q1JvG z1E4p*M)ITruzgyqo#B5G|`mZfbHEdGv`A z7aXw5Y0rw?Si%RX>Ok-s1532qJ7e&jvJ^fa?0L;f6tt>EZluVE&C>7s*>4JN|Ob_$dWvZhsWih zs<%&V?-SK(shdHa77JY2LrRq5m5+JOfUxp@^UyIInJi0at%m^t!{MOD$m`4wg1m9%wlOc8 z22@9x3QU;GXq;yU9S`H6RIbsDj*+x`>2X^>R4uk-s#Ii=;FS}QJ_^o)ujn=w%(cR+ zw6LrKtQ`S{`Z$}^EzTvTZIp=^Zt$R~rVvj>KEdx(^X2ByF+SKi^@>V863%oR$t&*I zQvC*kqVZjKcMi>Wy~ik5T=-}f)3mpHm%1EA-4_C7mBx!Gz=iE(2HMI_J}TzWQ!0d| z%$T_fIm)_dGp!mM_3GO&nQW*PjNoV)6X>&W66KF%)wsvIX=S+;CKp1q1Bk)oBpGrO z?&uo_``QB?Q&L+}A~Z0T(||M>n9odTF)OiIewynqW7dq!^Rb0&(qh(0BV) zQ7k^vIq*UC&@tC!Hv0|Z;ZD|{B3N=|COD?fC0RVpbV)xH7e7c zGSq6J21H2=g(23|g`|%VMl=i2+9|RB0O)Uu`t=mV?&DPyrUjsExNI zkdHkDqU?^f=+_q=`*RAr%k@aL_U1m7d4^J_0Qr=S0pR}tNKHtaCUW1xo_R|rKBS!l zf4tkMgi>8-OYuqYIso6>tG+Bm+Bh~lGJtxqRtqQx{hMCVKaMm3%B3k%=er?CJjyx= z1BW_Wl`FNDTTfRXN(WCeK+rkg2>W{nZg#rS+nQSe5v}V|p9Q4j_!vo1`KXig&~112 zOHkWF+&uxn&}Gshi17jC@bS=cdx>03R#(itbUu0tkHseQK(cMhjdr6nG|Xlkan(`fw1pJ3R8k25U=E~`KnWdGNCQC3{f(WM*8czo zyJ1Y+3)4|zHT;o@6#>zk8!)o*(A zlDTy`OL@$k@`8FKd>IC(xR>Q#AaWI- zOM0ZfboB3lFM;8$gt+8v^b+KP}Da$IXb5-Sn_86{pJ zq2LqYfIP4?9QP1>NYkxqd(h!bLR5qjr4`^HdXu0F9j6_xPs@IxwYwv7l`N@ERcp+- z;Cu^hA7AZxXa%*$dettPn~Qc!jxE;;mbEOBqEAvu@jm?or^AO07k2O0V!)?UA9ucx zhLWb(Qp%R2(X=FWTF;V4UtA8l1{3U*`aV`}*HdXb%f(f;hvk6Wnr)i+3Q9=9Lz4*T zwGR;3_EYFjT>)N6gGGjjH0bT2Ew&KTO&}#LqznK6=m7N4aNDuERNDrI?M7^nUMW4= z3c8b^8r`8Bd{H)9%b$N<6;R}rg(8(t4tq~IJm>4Cu}!XmMDQPR!tc*bSwyJ`TgnFtPMp_BY)Jnnj_Snx>DTnoCl7Lx_X zoLEatAd{e>d~5L;O`+53msQ78OnP-XGTnJsbv zn!=U+RCJsqd{2q^=qmadex)~+0Ft$6FArpYXI1IOKM-^szM#{Ui82F|XDPg*6l4%x zkfY!^M?s$z5$JRcd&5T$du_w^*3tHdYbZ@Xw)Vnbisv% zWE7y`O8KADK~!69Z#Wu2B}zC0KvaH?w`B_Wyx-P0OLORpHbtK6bE{4|-?1s+LYj&* z^fSe4HeZ$8OUQnXy}al>^YF zX$l{a&~>%CBznv}W#-$#djr7wpLd>s6mI6w z+?GAZHrKkS&O)idaG~}Vf;q5$(sSYtgMy~iAEZs>cQ^+NN%I;4pV*z+Lo&#?;_MFP zTq<%DfCUCzhkyKCMEQ>tpO>b9*-&fr%gWwEv0Y24b+A&PbC5=Yfp*DudX6LZvR%P# z(}(SON!i&VhD!yK5_Uy=rADuT5NO@Lny-VQIliho8XtXd@`^ISxWz zMnaIS0T=9B?F5stTag!QuL{9UzgmzJ6>hog#FBbr+?9BIaiC%ikiRLHbqYL~vJ$j7 zfKqdy#^V0~f?Fqy{hgV&*91n}nh;#2PYL#!dmTFZXBq)tFSE;uEvLO4+sm_P>r-E4 z{_Z6Dbuq`Al$_xz1pwflna~#A%&rcT!hYAyuiSLkq1P@3nGQvl${uB;CpcJ1AqrB| zPbN<)LIF9>g2c&ng(XVm$;N_`amRT#M2TIkx}cV6(B6=>DByc3>G_eMR_-cq*_W;B zS-WOBRP9cp^o*0_rJi5Q8VE~4VK^MJpS(9t+qar$ymF&lhZ(d1_KT09AbxrW58LZo z_H9q<2|&a|H5nm4bT)*e1MtvFFM`BmFnv1cBW>uMBf|}q;FO&O1?>X5+kvq+s+*h{ zbX(Fpf>n&Dlnj5mRDN0o!`)h&U??)LXOsc>4Fo?i&h|o;@6c{6WEIp#KZs}vZ()_N z{eO>bvxLiJl-CmJIPeHUmQUagfu44)u3K5xv4EwhkHqLIcW4b{Qm9u|Xc7LSYR_2s zmb<_HNuX0MB4z!4@smFv_la*jf5zgK{PY?fsD`PRYXg*=EMw!H1A=x|*evY#1zTTY zCB8*QwOg4aV;Oo!?-WnsG#ytJn}qZlE0NJ70E2;@0_JwoaUUZ2-|3djdF4?k5yW=V z71O*|RUeOrfOS-=vT8Gn#naVYI_M=`p|omMsS%<>isR2bq@}joPE?|N02%_T*{RsE zxjackV{tbHLWO9uvGt0?rt+6hn{m_r-GAEqBg;NI0#wIk{{RZsotUdG+}Ws7V)s0b zO{ub%BtCJ1wGuiL=sYw7C$y)q(R4;Wo9f=CUQ~JLb}d#LGb6Z#WGxOLC?C&3Y$&&U8L?1Ycm;Bg6QJg|Hsy-^HAZF7 zKp9pJg0XJ*cT+AzS@s_)XFtyJ^c9}$YZFwU zKJn0CQyK52Cq4k^CS9e1JLZQjI*kJ)b|_j2wYUhhIa7tzYLezJr-AF-_;swK=90Vl7Pfp)ucc$0qS+=jMxmr%?qGk;mAr7GyT3(qP~_fyyB zpcYpIqcW)D#OJPq3qiHDR`e>8C4fK&KuUWeJ51*A#dI^a*S%#z*r`bhjPs6rFk~wL zgXo3+N3WiM?Cj4Q_SIsD#afSDVnZuHKFh%4+ZmJGExpA6NDJP*x$Ub0?BcP0A!j%nWxh$y!dW{Bkr*&5> zs_a{u+^D+}WH-|6c?_!xLeg>w&=PJA`)8X?Dm9(Fk_34ONJrN>@P+%q^7tJEwWRUw zwbgj2of7ztq%33~tfT(A2;YgW(k-pFEXiqN>taOJvZO_d!@){Yh{jGl27qf<_qp4G zvm&hQ%&tSKS?lU^pvGr(oGTyeKc0i4pl)Nl=~sXLZ3LBOZZobFAy4N%BRT>b*u%vv z%O`l#v=utKg*v#}l}&AH_E8`Vln?I={KkOETK8JZDN1>1G?I+{Zm}7x zW5=1)kLRFuEx%>BR3{=dfCCZPWC7$7(o>JiL8jhXpX{x^sL2N(>gpesfpvb6-r_tr z9*egvJaJ5<2{IF(_KqYg^;ysdnw#cK_g*K(XF=_6KwV0+9wTEs&J5@;9|1fn-JAEj zR{r1HG-n=NLZ-tDQd=Y>DMLSka()9q)4Lh8RErASrC78mX+#-)BSEhU<|je@2OV*p2g;o1$mHf5T4~ zmnOz;jX!a1$?NYUI*~PmuL46k_L6=6W8a`)E)6)$vbX;LZRwX~y=UhZMv5e%Cs#Yf)9}%dJ6Ts{gj*`ZzalZ%C(~XE^~|KdPN!F z-+A#K2SGn=#i?QJhS*bfhimA+v*`5VTv>5^&q{cJ3$82gE1(|Xpx#H_nD)wh`E_QQ zK=CfP0Q~eFHMPHX#lVj4B~mNu1Fvx*D#yqj2h~#Wr_6Y*3Ijg<28On(9ZfvbDe+_v z{{UEJEB!`;nylB_q(xjRUvUwVJ*MI`mcjV)jRZ@$*W7wUDHEhUgfx<(Gva+T0pql{ zv`+26ZyJ`=ZQXrwsc@WAHA&H&!k<|2X(V_ccy#eP3J-E_1g4a(?d21mq^l(8ImPZB zRZe>@s~PpsZYWpPO-lf}tREtD7Gr^4HScZ|cN#6tMwt4j&pw~p)YjG09&Vt25FR7% z4w?h)!#5T-ZuHo6`@Y?+F(rv{(BLh(k%Bx&{x(V_0Jiq7&ZVu%wYriS?|Cwo8}V`FdL;-CvwWrl`SqI#b| zJxTP?4X!jhYwK2hP)rZms8`@%b^G7pp$nFgY~Ed(4P_1<3J{Rc(w%>ZqKgwfe?LakbBag zpW!+EGBg18@`#j5@6w)%86Q0d)sIm6yyPS+!CC_=^mR9lNUmMGODb+rA}duWZ7E(0 zLFHZty(h23Kx_8yL6a4{tD#PVHu|L{$SQY`WDNj;?eEwGs+~*U3Ormp1@xv-Nbw(J z=i)z20J^NL47^+(3K`ILd@1k3HY11|TXK~vk*Z}`rO6=pG*2r303vh-qM5$*n~sXz zZh=;9_|jVoX~x%(QbtGRppJKYb^(Iwo|Z9#_p|_)wO@%O?^h5~>C}n+?KXhfgAk=z zN}SGIU*m!D&{X{epzPM#ncJJhEt6(KhF*HHbij;;z|MK(ARo&*2PNCuT4G6*rhw#2 zrL+;~fD`<*5%&@kn)>Szin=6~C=CZyBa#&~tn}z~5Jvgl4Z~&79v%nJKps12_`glR zZ2thE>vp0(zgtOE(v|gQC_k!?<)9B&)ylbYRMT!}sRKdFAq#oHl;o*LK`d-`($ucH zs}WW{{VPA zgZGF(yGi>gKB^}`R^h>oLS<4PS$0FGD_Xo%bQq65xe6}0uD<;QJ;W7k>}L@a@1z_rM*3-sxujmmeQpFr8EvmA3XsFsc!!O)uSkhSV$QpodrYV z{{XZ`g|T*f@#*yxNw3XqNTtFH$p^!|U!q6npb$50^IpI1Np}TyqU4!#q$$}CEmlK+GdrB(t4FWKf_+Sp0z|eEtL+`|UZUfMu$w~-G87lA| zx&UX|#oBvSx+>KTn%cXeZNO=2Zn;#9?iD3|1(YawBzO`&8Uc-8xF*-7m91*!C)rP~ zf^*=fgDuA5UvX(x#j9$~sY*+A-ifd-50tn6djP6e#W zZSA;Js1>ciF~L*)&{SGBMoTf0uN8k2r`l2L;nP8OrBxegCAhyeodkEg8_jO*%{9kn z%}V5yo<>5lNze~IJ9z%IHm2Q~eQq_zmcRr;fQLP|mE?q{&*Pv0{B&{4d2uPYQm&fx z<)S)DkxZwhe#B<{hrLJ4=qlwxqavjszWT|@=riG<-|fAfP`WEEH5Mw|D{vvSr8z25 zIKa>!FQc*9N@vz#acR4@_*DkqkQYIXA-`s+Qcu|_2kkP+>Q&&Sk3@|D&8H#CZ9Q{l zuP;1Glum*P;*WS4qEcO@M36biJor6H^w0wS+b%U@swvnza;g^l$`99^ZGUAxC~M+R zQ|=l84|!G>Sg0r@=dYH7u-Gl0s^6D9T5Kq5TAgtt*g;Y1KS z924->9-(v5QpN9jM`}%EsUy6n!p2&QpCWV2uToBe>0ei6I>?|bCB&qmzg+<8?H1#T zowHkcSH9~NB$C1uihNS%SKmKnAbIuBFV6k(CvxsR=TW<^TC${0s7X_@7FFha50cVT(DAGWK!@o8=IbwDH9bL2DtD*phkzgn$2 z>#r%rDZ-_#MBRt$naA9{RV(bUstwPq@~{s-~*uHP1v=`z;n;n zLEdfU*0el@hkOVlu7QC&DtMQRynHlUZZ2m$+B8(t=K`*vx6vg0Q;)+zdhGhMbK@l$ z1d*W3x~#Tpkxm%|sC58n2e)b`WUZ&fMWs6Vv*`$hbHr&*GW2%9FAy{HKJPsM1m1nD zxiNeF?nK0%!!^}FD7g$X=*p7*lTO|8m@%b>5Zi;D_%abj{xZS_$YZEzIp;tSE19dN)oVysHq+p&U67^ zw?DG#Y&mc5{?yyN#07rTh{Jzqc%FmtABKP^?gggp9&)6#*$65;z>E-m`V0#~;eLfv zZNxgHr<@Q{a8iAA2T!p70JQPD;*%R?H!``3-8qDavK?Rj^?`sEGvc)L3Lc$w28(EK zihW_0d7etL0S7)h32AfGhKF#V2Pnn{g9&SPQ=Q|=C*pJ;GPzS3e$RqVfLr#`Uh{2E z7dHyE0z#R2;@lP%Jp01FVfhUL*>8U`DlRggvW4=Gfa#!*nr%+Fme4X(a0Y;Z_9Sdg zYj!x@+Us5nWhnmuOJPcP3HvRu;CV;j0yGVcW6*gf%BZ@Yj!1D}k?Nv!8(Fdw&Zn2r zDbQEmA$I~fnEP$KIa^5`51xQZ_R#Sf-Ji2^ZJ0B{W!K*Nqe)7-hP+%qhfkh>A?{7U z9(7E%eDDT?hw^a_u?`EsmD~W-CuPn6t^+{vs8}O5B8i${(1)v+DfEbR@j3=WkD&Y(qhF*eK{FIaiE4c zzrMNY^4$+%EJk(H*Z5GSe=P#Oagl#ZymxBitx1qpxs`|1R8N;V1N6{C)M$onO_<#0TEb7OZS9`3qL(UH62a-FZGS!u0QBfvv-TcTnz?1`Meyiy4JC<^vQG2l<8fJ<@7!BxY- z?(j>prLf}Z&aF$PNpU_Y@#H7W?G1HtI@?q zN_kppW>?*hAP#zg>7bAi$EOh6n&>sH*QmCI9*seFxkcdmk5;r{@9_ui9u)2o)= z=+>WosVGp5B2t`7m^mY<$j~vy$J+NjV{9#oz0m<}&#F-4OOVrv!jfEUD+k}#LD^hf zJHfhX4#BKaT78$>DRHMz2v9ymXebvM-$%b-_nuU{qRoQ!yHW{X7Zj%Q;qvR91;Xs?i(I<6n6oML zUi0f8wpdaMGnC;&u7QK#xT<{BKxtX-&o4vfG#h#H6lsepIQ9;71CzEAq4hoxw-La4 zy3BU^`^(4qXcr#)SY3V09}b!c^Rsb-H;9WS8)w>b?WUl7Os2+x&TQ3%(`pJy{{Z8h zei{xti5Ut`*VGa`RM8zi8U>#EKvm}_@tJnTN{=i^?6Qw=@c#gpKrvl8aYy?{K`C&r zwY7cE+^T&JkxzO|iE_}yc4N2BwW&$~1dlRFz#0aO?5FI{w|F43Al`SqIfr)!qX2gh zk%gj!(}@I?EAPlq#!ubo1^@#=e(f4lG-^^`T5x%Dlc4pG@}DYm*Flci!R0R!u@ZO3WGnV;M4t9^6{Vr%r4FDUn9wd3@$LQ3w|7ljZm!4=MyOLH zttmsvAgvi75ud|BS9gXy*pi)a1q>YoT^{S3O`a9rE1~PxL1#E394-*?>bhCEb+o>i?thyGcuQ*Z`JpmujL4EjX?a|w-?j&n#cpX(9vH(MiaPoz# z*9W2b9R;qoIIFa8YI0}W7eslDEjb03fg|EHAIjeCwJEX_BPu@q1yb!5;&g3R##U;v zCxlH~1(-ZjZssK>lytL2~z_2|>*rB29oPCDv}-El`HN+%?p2QMzdpHNxkX;?mZ z&}?mv9xl6@T4K>H+4TpOeU_m_an&D^0nkgfhi4ZQ)mWl^Gl$!;#(>Xws!Ea5{8%~- zHQ%!r-qFt#%kIvpQQpo1DiGA(eZZcF@z6-zD)Gy@93WScsx0TF&>VM~O*KjA|Ui7C(UQ_&{3LZ@Uc~#sWoT*wCl?y)xNG`qI^luj)La)U2(Tr;m3I?kfYXI zZr!WOLo!${9$3p!z)=3lJ|pL#Jg{qm^0yhNhlzV2UoOTfqf{O> zwx*>iu4dDE)6lR-@wyN{H4Ou7?d%oCrb|QqJ?itHUSpjHJ-#;tduqm&Ag|k6c~Uc= z2Hm`y;VR$SDE2&AoUUAT9#_CuUgf;0L*_vIbO7f3shWjhUe-cXeDogsZE8Jp*P3N5 zAqXCRGaj z3wDGVE+ru;>!2AuvmKySOBUI0Yb<)nVxd?IZ3|_1Qw$D{Iz1F~$`8jtDB)i?d^8>E zRh1~KsXqMyPWnGvhV5_qeYdWtl(h;yQI5U@FS=jkq4;PCMaNHV`XMBEqdE#f+6%T& z_X}xmOIgN()a5z#pb_KB+LTA&4uNO4PM&D5y-iulqdc~c_*PT=v>as?t@V0>918o| z0uk7^yrXY8$Frq5Af<||gH4gwp$`sF56>C~Puh3ZmV*xXws3wULD*d_CF)a$9eH#V zU$q-;o7}D#uDVHNDN(6z%1=)Y>|~$AItBi_rWo;%O3r(<{)0gt)~UYyBo+KSLpn8+gs zkRKI${Imm>tx=IuoaC7=sl};esl^==PPBb@L~#g1qq|bT-9ksn;{g zzPQjy8--SCnMzqMV+lSw3PZ)#^3!cQdZk>d)Dp~Saol=CidRITAd-Le>!4h&GPs1P zZ$9i-Hxi*GN9*#GA~sL;OedphA1=QWps!M-E>p^VXQ?_4ziPJnrFd4EVl*|nr(6ha zw5KIRo`7f%w_qP)Vf|N<3`jv4+mDBW0ZuA z0l{s!)P_L;CDM?P5}X8q&?FBek0GGLdDkCzy>VGO4>y0SSHnRK?)^1W=E%x&3UD+4 z@3!-6Z;Dp@vwzenPX5fB1*pbCP)Y!82}(|UzR1uG?ZdUX%G~70J#&o&M{--Lit?70 z$m{8#(v_w+QgMw2{{U_`zVO;hiL08)tvwP`T?uVO1&>4OG!y+twcmWCTEDRxq%f(S z-zb?Oi-G3$`*_x}KQY4&X$aN{}xf=EhIbOA@U7qq@ztlZt2+pB~A*Ou88iOjjy zBWnKuW|BM>N8z9kcO}I-;heb=9a4c&BPS&L^b+3)JSN|~NbV&v*tV^?l?SKIM0il4 zv{dY;RC+dn>*h)5k&=Dj)*X;Nl2#{Yw%EtI?)qFQn~76|l+Tvh0dA7X8TzDhd;t5) z@mjJ@g5g)I%rMzgucfw9GNmZvK?HAa7F0W7hpASyguM6!DeU_w&T(_-#a$QoCBSu1qYBE2C3I2X3K>$pf zB75ceE)^1g4F+wsZcVsnqAYflQdQJ}pe)^p9gi0m6#Io9;=Le0Pqe7&OSc_Vwnuc| zL-l6Qo9+&WA7Ll>k3eNDvD@2X#&ng!JqL;R4FdRY*6!RJ zgLY52?h3Ny&YvYuNquVSwW#&^dJjzp7iQa%u1c~SLuFY|@EOj4?R^{`%4A))6C7A> z)wUOJThf#J7Bq(anw?2MWB`8CZ1|JlSN+`qxFm;0CguoydA3iaLeCa*p)}2Rn)6`hT_<#p)2-Ya2ze)e_n$@MQ7ad zDzy><$;!HQ&|O~0jtXwxG5D6YcDj`fW;D5}cC9a$*^Ldd6!VHcKqsffjRRiVHubx= z)^sa=*@TFcsy#iZG^ptq4Y1NeQ`6s!{PY!HjNRvnO^GcoR1(t+G_}ZeO2A40$tOUz zJ*Yfcxx^;+R4X+3id80^%@UN3ZiN8*OUL$)<)En)I%C!9!W+RQOY5Lu{{W)T+3OaI zOQ`Xod(aZM8Cj*-iG8es@gKjCocQvLARlqi97zr{Z&Cvw`&^{0MD-`kodERhS>qNa z%Wb7@@(%?$36jk{g0JgjFQNzI*X5vIZQ$Li-QiuIbKG@h%AY<$-jw>+lBJXSc@K7i z54x^$^UFQwpH8|Cd5Xy|=bO(#+gUZ@hmfv+G3THo{f<0k!r5)Ye{U{n;ktErqq$nu zgrVW#_~;Hk(rzS5lqM#}mKNKn1quq#OxD%Q8gdesRx)~I=r(n$a+_VJt)SXZGIRl( zw`a2vb?CBqfZFN^MNStosu9_59rAqhk0bdV07ARzF4H9`^fIJjWH^Nk6et`JN0A3X z-Ehmq1>3V5g-pI}Dx%}hr#_XV3&3$X_K>eoM@<7K_G-G^hW(aSPullq!2A9>0mE@oAEDG29mEiv`zJx)><;bRdv|rfuUl2OVAQG4rRZ{+ zRtgk9P<#mU8Uyp$FWS{^?`0+}g}4DL@IB`?Qu%q4zZ;tBCV{8D-!T>)j=ox+86 zQrc+ANna@CR({aXb)yJIMuX-^?;@;tWhX!g&oP6s!Jf{Jk~#B~&%S< zPP1rgMu1ax#db%*-U>9W;M!U%O;=&IrM$~%z9C;te_4UvK?abNA-K$uY zPn%16B)E?j<-~OuQ)?a|kLTy0+wi}>SEmg-txMdiRpq7V509)z=E7vMdM%}Ui2U)O zJ=`U6vt{qKfls-uJBbb{<`Si_r#-YBbx9sX9)xHn=l5+ZjmTtVk>i~Q8Fyc4<@)N} z2}@3;!b$PMf&N+mO~;gobp9l77;xPMuiHvuGBS6l5oPFZBMB5dd!Rzi0ev&|OPRkLa&B>+O%zKs@_!?}u#u7q<$q z%f&95V{sZF_!l|J{{Vz&6~B2Wt;>aQ(yoo3U%+TCr_sFID0kmzg%+(gAaqdZ6)J;8 zNzW^ZXOSxT73djO*4b8FwgiI^5~i}Fk347v=WlNc6zk7t<=s$esr{u$ZEiH;QP{dmNFyN z26Yp~JlE3MDeAMpJBp#VKB`x2YK!p7obi4soY#hvlihF(NIWVBcEdR>%hyP(cu4r$Gm+EGW!}>)bEr%2DhWp{eKsbD+ z($ijx=A4e3t@oA@S0v&pLLh-veN36j7A$~9-midjZ|sQRA4Cb37iUR$kKc>MDl_ZD z7u{v9W8;|ZY=^NbrCSk{2YwRwUH92M02ZeQ+))|M?KpUn2l|cful+o*PJ*&`A+yyl zewFl@Y<=){Ak6>h@_fF88C@_B7Q6D8Gbuggwvj&XjCD9F=c_0nQgzyu-K96vR!3T2 zU=^%#%dbOs{Zig5E~)XH41`&B_|T<_&Gke;?;!}Ce=D}Hp$xI{aNA%bwn}puDU77M zm!_@guGBe_Bl-;(aHr$}34K}dC@C^sS*U-LdutSi-pnGQ& zNj8G?&kWN@plvMj?bnU|xVYd2DgqMBHm zZXWrB-1HYQr&4t&6Gu52rE&eGT@y_fiyyO0j6a`-gQpqjiKaf}QS$b{&R&D}Lc%jeq zvBO#!UmVs;snNucIxZ~eR^9l~${!(DRd0bc3;+8y?u&0>3K$Mze{fZ2g7C8cfDWJ? z57NO*wTE4-@~xsf2T8Vr=}0pTzSpZ0M-$q5@n2%~%I4^eWO7xt|DEAEG(vx)x3b+t1qKi%+m(%g}7A7$lQh(*R zQQkxm**(*0#`_Z85*?cpw{Vvt|Hhz_FVU35ttex26Y+3CxqC;&|GnNry9Vci20i1NM59;A5#8 zDk}+`F7)s!^IqbAps&(G-JkgPL!PHnO?P{p^FBa7OJKC|Z>y%mRfZw$b}xG@voIU| zMmDCFn|RzZ{xOwF@WAy_3v62XD!5fRXKkM_uSnol!ru`HQI33)VEeIX@51gy#8H-- zoX$eZLIFa&GgWt8B9uesKr(dI_?0XjP2vEE00xKBnh@dYfD+~OP3TJdz*-xJ-1EHG zdm5D%9|iI8Z>y`42Ela3v)5(g%BsU7U0%37s4cWp%$4TaG2h(KyU6~cKK9_|r>o*g zp~R08m_|N=Y}%Pm2IvvGpE(`I-e^|yJ1}y;QL=c<^s=Mc4Y55p_2$U%ezTQ!dYlD~ z{iy$1%+ewd{OLw$$*@M_Pm8OF0l0LoXhcj}qdkLph!M-d39S(~?L7B9xB2yx)JY~g zcWz^?wOZ^X;|~Iu$-37D@cqGML&&|Tu)-B)@cnPE<%tj!`*$5mvs>meQ4^O0A3GuxFk&nZ2#2!co4Hf0tNPfb!G z_A|fw{8UYxc9*BY@BDtRIPk|T-FNqh6U&#Ey1qS#UI6*uKhojX$Iy4mmAC)(1+niU z5jcOAn7I2J;G2&2!U9HFPooc5dH26nh#TGyV#!k1?Js5or2g?pFEGO!FLzdNtE&AK zzo5-S+xsVU*ypK_;9P5AS9ZrWX5xjUbo^OJi8n=ReuzxPt9sE)nHufKTD&YY*BZ@P z?7Nnh$HgcI(tQwfIt>{*Gb5u+q_a&UY{Uc3cbym49bka`7PO4DR z!@6ZtC{?c+^cwnMqL`z%hQAug+4{TPPDK=FU^AI-wtN143YptQ$!>3@`H=KFl#kkb zkYJ$2U^5ByBVq=Cec(hpa@w(*eQhWmE}tRW4ybrGPWRf}U&7lf2@D0@SGRhP_qOdA zI8srw_i$fIa$M_Yh&6hsAiNpgoE-SN&Yt70Ky_@?^s+S?$Nb_m+V8)Lso80*7$=3E zoN_`D!Y@BYTjiDZzE~buHk&Sd7wBG;f9}>XC(-( zmUih@46EsUQ-P#wio+_A;dHKi^T^?s9&atz zLKbUFt&}U>>o;lhShAzJl5VFh_xLTa+CpTGJLRZPJVK4Ql*Tkm`uwPXieHJdzAmD2 ziGIJpVQNX)o28Ty*Nd_|&g?Nh#?yAjVfd4f&&=jg>kdUEMylsF)a-HU&zmY!g<~AK zYKn>``Es$=8Ab7~{6hw6_x<8qE3jtz#rJJ_EFNA%4II>A>fveE&7ajO0i^Ndv&haf z^NIH=)q1|RC(QgwehS8f) zeEL{_m8uD2iuHkDFXli)dzID$_44$5ThK5aZrYvH66inBVZ*O;lVYDqENY*%#%NjZ zPDzqXiIyb2EK*qT-wTAf*+DyPGk-Z5_P_3;Sppt7Pdajh z8ZAr{+#J}nevZKG>TRXgud2l`VpyR?sCH61DR>56e_3Aa@L=@`_Gw_E)Qj9Dbhi}0 zA==%BdI*rUP)x0FenNNUHWjf}nUyL#JY}dH3_>w?dEHg24I`YcckUFL9Y)f#UNx7L zGNCbVeGX6M+W(zuE!=rMTFa^w=weu)4U>^tz1EL(81BBy+uMA2o}0VSHHX=#x9bNR zK|(Ys^}X4+FmVSt9wsQByvKtwI6^hE7@&(E=htA_s8$I7))Peg|%)#;I6T zy{~!nmKWBUZlfKQ7KOO}^g6VwEBS4po}c52ozPvEkqW%pgZ@*1UXM*Q{x7CSrDdo! zI6|FM?qvPNB#@c;0qRN8|Y=1cf# zwB2|vtL85+k(sK#_jf4ohW%^#c`ts>c1|Nf@OQM4+f!~z)c^^5$~1Uv<}zLPvmW6n z@U!BlmjGW`?yqE}tWM_FP^qrue^q4Hjnf~8yQ+x?TkT_2nd~*K@}x0-@Ah+^NnjSh zJL=Wjo{P-Drx;iQjZn3Cwksl=?^>W>CS!s?q<3G034no{RaVD5FXBxsWEE%kNUk3O z)`8jl6~s(gQYnY*pF;twyLCxo=aAUL0OUn?^RS7?gNo zM{>?O8mA&dU=2`fb9_I$A~*lOT3+XGald$6B1Ae5K$gRa7-Pvn2&9~eRvXql_@GmA z9dj~q|9Lw@T0~kw6SO#2`&3K45W*uGyysTL{zRj4n6!Hb1p3^K1_`6d(VXpmUu%cq z&TTF~n~Nn1pK%!xWJFB51OQ4f6e9r<0 z9Vj_-wy@aG(%b$6u_Cyy$>(a?`892L9Bl-CC2tbaoXf=k{F!i;2x$coUC$yh$fg>B zT-XWAmL1WqE#LxaF6}TeQimUPWVCwU1-(S-LJaScdnkF033~AY4 ztYy8c^=2G$E*C6Ym}qGZu8EWb;N-0NMt<${6(vZsH`b%JQ7@2+ z853Fb=k@OQC}dj+C~#AeHpZP>pZ>rtNewf|oPf~Deq1PQAm4_1xvwRg8jc$wl!d9H zDQUsK$Psq03XEx;YE@6@2$uU59~F_+pDKOE+zKnyYX=$FSYhmb4?&>o6e#(9!Qz|W z8Jee`3qOc5#(8SxueVX?nHqynrRAl+A+$Ofulg4xclE3suJ6+0I6lc9Eu^ktlutzW zJ^(`edWWtgYwf@5(w;6!aso+VSfiGgyBiV$;)Z-B4ihw8mLG`jZzl7*QcV<7Lcxx5v8NBAG8FWQMJ+pGWM z>I(LEGg%P8U&2?Ns0$+9h9>(?!=BorzrMa}qIUAfQBNJ^m(JksOAG}CkbVwTaP>JH zTSEV=UO7vo*2yf#^jv!zy$(%U_IIhM03!Z2BwD`w+=lfU*z2&y!Jv_!=XALChkxon zFRedyE@L%Pb-oai`BfxDo&QH$zkK>X5ZUMN7_JwwRWEg06+6W>rJLR-A`Tw-p8}B1 zuuq~q;1oY~9r3;q=4`~%`l2i?7hif{)JIhIGcU>Fz?cp<2yUMYHEKX?vSiVKKGR{G zBMaY^{aI8y<78swcTq3@^D`ru-GAQjhyOoJbKU>a#=D zH1p&PlFr>rgpaB4d>-8Q8L>uldY#ZfJ{Yfp>%HL_0-*Lj$%(>qYq?ADo?a&W*rf3F zbt%?WM0}}5ofo|e2d3iE=*}6Q%$G2m4xhcLznjKag1VEluua>0af^S7p*~X|q6{%0 zA;=KG+!f5MszB{}gB9&2n@BFO*3RA~zT|D_MG?ulh9N=t@2R&@_^Rlf?A`(Nq@brF zCbyX{%Ac|tJh0Mfr_i|8rCq&@@#Py>H)=2(lKgg93O79e_}aC@;35mXT=5-kbU~5E zS{~Sf@%SGIX*dct;{Eqy>7yx?zFwgVk)5UL2(4@G=8k?Ic4gnS>+aJ)E8R~5N537q zRCX{1r!&$?EjF0*L!l>GNPd{9iE-^*O+dB9`z_peRASb#?QmPbY z=)pN1#&Bn@*ouj*nNL&zQkVM;MUiB-6XiMcVFA_|Lh%^Esmr{d;Uz7GaIFm(8*<^` z;iN^peQ_zAlL`)>Lj=LKLv8CX-!AXkN` z3`p3CrHMe2UI$wwMz}i|mc7w-kyv8qx)4XuSpb$pDT%wK(TLcNvc#npr!v|kIT!h$ zAz{v++n#uZ{7|YOJs~`iFnextL&K_C&F)iP|6NVJW@ZY_@Q%~lf#%v@b*sZwQe60^ zo$*4GjGKw%hb>9|r+}v($M-)_F#M}-n}+#}T1F=8b8X0;Wj}9r=M6=Xf1(gBJY0aK z*qyXVh=1G$pBYxnp^1ItnHa}($Z&yB?r3-hT(*)}hBbvSW#BJu?5?9pnmc}?Dvm2E zR8x0f!tf27lD^3#hT^(J;e-3r6U)K9&xxWsmT~_8Bj>P|E9>l+B9svuZ(-ObO}GMgb?c46Y0@N#A&)L;DJ?R%wiSqT*FQ-_xCQE;DNJSTLBOM%N& zb{OrFRp*u_WqtNA!V9jS#AGI}5l`g-u-NLS7}pk7c5ojN_6n+B)}O|a&!-ddF~_;p z1Hxu<2FyN9=Uoe1c+|QIi(dkU*qwNg*oY`t0w3jTN9Scfn*4XKo<1s3!kbRDmo-Tcv~3dwt~D$D3abh+T!r*}lx`l{*bv5ly~ zpn}!AYFa@I!W4q@MEatI>PEvTj6RS$s@J4+Q*{&|rptUA19GN%XpXu}5=gZM$;L6wd=+6> zQ979Jvtcz0EMc-?9s~!94K01Ld$q&A+eT-Z!9QzzSVEKrHF`uma#RK0c3pn$>@KG6 z(KEKPzL0;SgT?$b4O%<-*T*{Y$6pRL10n1*z?I#2w7qE<_|fF_4MhPCcb0igWoJKyk`hqkUX3N+E_enz13gDapS7fA?<=RVfvT zC!9$x2$QFgl63lgMmZC27~)}n3ET&juS}e!9j^03y%AWSUrFkTF2;0(LmUiE+x5BU zpSWacrk7-J{s$8NiRQcif*UTg9(PT49UkE!`)!kA5@J`m)$ReyAc_ijxFE8Cv$dDV zs;(Xr6vDbaJoBxw9xf;tXt**bUcNN76Tk09DtUE(0<^bG6jGf(i=rir0GlBJq=f#l z&V;*aKJLm`s6nilTchP%^1)jw1Z#fB3ya#VVw=}^D*rnP;cl(#3paS7h*zk9vbKLR@e9>%JKavSn z>0yFBUCbAyXthmNu+DJa@xr@sgI($h_PN% zPDz4=G!{rOOs*WvAqC2z#=8g1Dzw?^Ku6XST-E_oA-?&}^`XGznZ zA{;vdi1AcDy>AqtjUl-Jvz3MBUGe+q>E84%rB*GSt3xOKtqt}IJ1f5^Eja@3(H1J> z<;|$fLh~OenlTmGm9p6WdFF7tsGn}742sJpl=A29VcFZ9*GMYh4tRYU#va_sdP^Vh zcr-P`f1DBqX>tVxTbD`&oZDf}J9E-_SE;i*IoBGRs8xzoQkBzr5*&F(Hm9sn?HCHrAvH;6JJrftcmu->++oUGSBvF} zZ^J;hIO2b_>NPNADqD@>mOkBq5{tpcV&&o4moGL)bogs$ID(b0R6}Jl!#>_?^H2?U zYOPu{@3d~F9Jst%eJwp|kCjf0!(CCS_I(}FgtmK;NU?uWWpgi|r)SR_KW-qnRVZI5 z>&+qi&;)f~p?9Up67JEem{ygp`X?b#gdLnbY5x`)*Z{rS&|LK?cWE!#Ez%0TwtF@T z4^J~;fT(^y=XH4sJDH*M-gZr6=nV?;!g}^2qe<88 ztXoSKGK@K1Dzzzp(!(wPwWQ=NI6ZVnFzpI;adu5Jw6A zs2HV{4j@6!cVHSMt*q_NgSn8Rf^pydvl9jPUzzx45$KWrwtG_k${K`Z8Z#<*l)#;7Sn%K|uek*;+W8yceCbPbGh9F-Y2=5<$r%NDf zDCw`lwhSdU>+HlU_GmdXSU2&qyf;o){gs?pl0=$9t8$a1fq8qxh=bHn(emY0)RT|V z{;3+aPuj_dC!c-wX^i=-5zw`?xM>;1W0^mnZ= zIxP4?EppPzHLr_gsl8fbx;nlPVEkXZql2{Kf&r2kM~-d#YI6}RsV=Hi_Cu5{8<@2! znq)h)j9nVirYmLLqU(?3@_3qAu6ZmYbeeod4wI z=615}1IyjiZn(?>xiAWT+CE%8prJB*8iu_{vaL^)#b5t2N!Wp(H~66^IkBJ z1aUw3i5*u;%a4MU>Ub7sW8>V_IK(dzjxff=zkkzQjGOoy$X#mtBU_NVsVY(+rgp5T zzb1dT2|YRzSw)XxU`8|7skCvhwRv`|6viF{3Z<69No%XaM5w>h9c6%-c$Re0m;u|X z%)-9JM1#$il*mGECJ-^M>2Qd#FAqxkD1y* z;Go(cUwoxmtpO0CUyq$1QB|Kx;NO3Fe0J0|*Y;u3PKa~W!=zH)Y{o_mj(;Zibk=r# zdL{vj;!4`bK*vu8Zt1dv(xy{DUVP-5f&XZRAYh^JWwyfPhUxNmK-4jt^)vgZ%Nw(4 zc2C~lC}9`=L56!{QgMyMZPP(1lJE?lFD4}Bk{p4Hd@oZVb`(F9l8$gMrEdpz0dlE;B4o4mlF(WHrwUsyieS)M$^I#P3NTCu zIP3*@I*0t7#nb-}6yW3^66Bxsdd45cng2GB@5=Y+}OQ^F{{_K>>IpI3^zkci!K;b&C~S>vtRxcsQ$R+Yo8)VTLEq4^igJI+Qhpsldt--VIHmsHGjbnc zzkXkx(#$V@I;vrH@o+&X706X}nE$`DL&oQJOvelTgM?{GxitubXSxA@K#lgBtMtsi z(2%S%giy%`oHiWJ5iyy}PzxWVOKxz-`mU#o$BpWCpN62Q1qGg8;p4UU4T@@N&$Fj) zh{I^xPyhflXmo$Iz?J>Bpkp zcL(hw$?fuN+gYVSFyoQgie=QR#a7NiJTOG;*9Kid^S!TO2k+C4){~;vgUIUN?0!Li zfMhe4=y}XRl2`rr%r#SQoZ8zdN*GSP6!OhsNnj}Aoj2pAe{{^<Lfzym<~*wLB(3Z zyJZ`WovDT~(gH2E0zj~9^15r5hCiX{7bvuZ?UbfqYsuC)ujSQH!;I{l~A&4v19v9zc7XGo3 zc1I3{y;bRqb}G+dC$Y{i;K!WzIlXQYo9=i96(_RWu0P7%yr9EaRxaZ+n3B`FESQk( z%S&=@(>z@Nao;i`zNKk=dY!RKUN8!lSQc#nY*Fkg+p1trP8x*XpO+n~HJ_R76O{sr zto2M)fafa#{O5K%{{vxqVe!WNnKWBmwRdT@sHf5E_An{!cZ;;TS2|`+45u}}5gYlD zEq{uz?p?)O)>g?33ie{`%ISnKLm(FH{)x^w`D=!;U(-Iq8V4fWu*W-*BZ$2v7luRms@X4YlqwT zTSqgTRNNJsu~R>8-Guo5Pu1}HLd|&js)sTc;944dy}TJG6_r5IX`yzUWG+aXHWq4? zBXxOB>&9x{ss>b+ko8&cu@~fremQb#aVFI9VE85POvT(M+ZEhos{W_zCM;k|n4$vq zjsk{r&vALlx%EnjvTk`Pi@6HK&fI(e{V4E@N;PNU)>Yr;+*90BPkY$#kxun>l8*|) zgn0P7NqJ4JIp`LJJLuRysvPz!;i_M@B>Pp4JQwG&Z{+S7uq9o#=@@xH{-wkx3o%3q zuG$Pk&m!i_!gsGsPBM2X9@I=EKdc@hGq?my*2RyEwe)KOd;dt?0K&TWU#X%7pQ6#I z7J7Nd!D4MFEHicKQ?G|{^w+xTeg~a{`FS8&Xc>Vk{Or{b!?tuj9Vvcd6+=HCz1BW8SIumcpsER* zWCQaa=kGPWgLcMDfY$B8BG#eA%Z(3uT)#}lZe)BD!XnfYs2-WD8o>WgLhHsRD zKHccoogtOp1L$6>-C|ouTaQTD-|5M*%g-IpF#lH*;?2#ug)hU8^=aXnisCo)jpL-M zNt9CfxHJVhf}@OH%^vIDGB#s>ITc_fSh!Sc->Bw@(PrZw)HB?AOChBqg*PaR@0YUi zd}9?oU3Dboed#&wSH_EDMD!{@M)rnuEDw*{eww*jQx>0{%8n54L%D5J$89$mT;#Gi z1DP4VSfQs@dr!fL$ES3iQR7Me@Z=GJVD9Hrh_58e^yvp@Z9`@VOLE~RG9hp+7#atgc>8eFMi<#ZN?3l>adjs z;YH_%FB*5!x*fMs;X1%u#t{y#sic7~a-+Bac=WSf`<9hKBrkup#{g{a!ZHCTx3B_M)SUg%AycY;!jlD!Cnk?X&oE*AXu*8D#9t17tT zv6PBonJ`~~cQX}lRMxaZtDeheXLNPe)&k$X!~b_<%?-Dz)fLJc65j0djvpHiW z74>7oAeHo+I709x_Wi&d+R3{*;0=oy$D~yh!!Cg;rt*Vg_yp3mbY}`$vt=h;7Zd!T z&(FP&fsi-J*5HY681jsOGX1OWuw^=3uiEgx`RM|Vu>cQ7w@`#^(1B>%DC-XLiV8^Y z?4GL}W^(Z3&4ahnGsplTQ&#PB!k@9CgH7a0Ygr$OsO!|uEUBOeCSq8X^nQd6mzP9< zxRF9jpOZ(r9iw(p*LMVZQtvratO8-m;;vBUHW17bZ;Rf8TA2NG{ayjP926f2*I1{( zB0VC0{$`k=Zsxse6UtN>Azs&OK>L^^S0*H9{3(g5jGhT!*@gxSywINSRms$jVR7;0 zMyuTwUF_)YY?m}dnWfgB`SWeGxReY`5RkD!W|NDr1;z7!d&vD{_qbtx6@2%EXA@>K z&B4Xm6n|p{PEaZAen`KrIFY8qFSbQ@D_EgR2dR~H~me%bC2i0q}KebN=FEW;G2x>SVYSTk>OF1 zrKd+PY6f`PuFuOhE&nh$tLU_}n7j`SMeFvc29N9_v?YqfIooAgycm7{7^u_zGU6F* zo~{dPl4KSw64`Z&Zn=KWaa}F4sl8R5!`WqZ?SQum*mniirgco9Jq*P;*)_nQ_Q_*1 zoK!%{xv5R>&R;+_q|;wTYnf>TAn^bJMItyR-pql6fdm&yG>5}?q~+)nLlTEZEgaI4 zNg}RC0={L$`rz}N|1uj)^{fj%hK&&0{E($>~)Nxr!*N8@EOK5Q$9%0@HNnBxo0UckrnWPW+3{RHFKhR~x`OuMTl zMGSqa3iYu|g5~7q{{<+Wr0qz_5M#iR#+%;XY24wMjVl1U6BRy36|R*Sf&Nu@z@sDc z6sXzoIfC(O#c3;cA(M$R-CxMN;VIxGJ65t6d4!3d|p7w7se{P z*=1N41f%4+Y`4}gtNpRZ#>pu`5(sX9+x?m2d18sr?n$&}N0?+;ZteBRag=`4eIS>j z`J+OBLqB$#Mz8r+&T6**hAXL2P$nkyV_sR49ikF;N7WO*ZbT7N zmWi`W!{b$^6PSMWM&(vz7tyDD=~P6fF$5*@UW#h5Wo66%tMDM^Y>sOEbw%)ZMbaEp3F{f zF7o@bi;4for_8^VR*mi}PtL_rPhL~w24S46{}SfFN7B=h>fQgyrj{~-Zoy;D6$69{ z+#X<0mm#hF1mejL@imu_^ng6v#+k&D1uV8 zUj0+Pwd1|$xEy*a$izl)iBRnz?P>n%uwK3-#51xn!+oaxz)f6T?ZUpre21c$ZlaFw zaQzybP&QYPI>pm~VAKD2ZVkJW-C@SMN;{H9<5Xrh&G1&y<$NY|DYZh%A)ZJO4E9G` z+mZ$zXatLjEcU;PiWnAr!%C=fIRs#>r8@9^)jqw?@^RYrH!E$<5Xe9IclPvOhJS%a zXE1QRaPt{xkgbrR(-23Uv9;REU6sA-?j139?>Z8y8E58vTUvUfb0%*Sv#$Hme#dZpo z#j8X1-{rz#V{6RzvjxIjz*D%kF)wg3IjUskZ=x+K4f+y_^N&rFeg4Hr)CXZ+fq94O z^fU49QGV}-2^ItsB+*tT z1|g&nY*#*&8aBx{00c@zFVcM76c(y9632=dYYo{|{aMZQ{(3&fCk@JCmPwSCwx4zC zH3DO4oPT7MLaG9zN2W8c!d@dU`O8hu`M%7^-gw%|dht-`zUKCCI;?CMg~o~+q~Fb) zw@KT|3QIcfHGjELs!=H|wbU51@z9Id=+)uXngBo$7@xOhEo^wUj0PmU&k*v49K-Cx z5Xkzllmtq+K_D*OHX?7YS1JI-z6@WYi*^4IoiWc8fT{8~r!6pDthC5^87?6QHOz%r zE2_q-IjX9*^`4#lM7;Vm*4O%!`}MNBsxr;{GlWW#Xnae<`X)47EDwsD{?MaQEoVPh z0)rf=DYMEZb_o&YAOSaub3#+j;Z}!^6Gz;P6}NlNefB=aBjQh}ueng`;U7bf0)Q>V zyvT!9T~PvMW&jD{W}(K=`hBL$k}F$A?@Q%c$T+aB^zK%a9d{=!_%Zg8U0omF;x30k z@$o7U&c{BLGyC#?8eh?ahY|RiOB!RJGJYj2GODWlE9d@}5V4>n#fQ=P=7*%@RU=j{*~JY-m8NybMz?e<(3i8e`()*oHA{5JLpx_4=|g9~;cv&ICgEgjrO9WI&N=}3=d z|9Oy{c6{3Wf1o%(DH(n%=~gcjtw~wKnB(!%S0Keja9crapZ%@mJjQi+jU8`+-Q${p z$eU05zLCNhteHcWrC8{iUA#45s6qz4C(F(droV zdYG@d8)K~fV&1Z18~+R$#gsCH{@{8^3|}iz;ueTmtCul;YjfZHVg%y&5{in%h)n7w z#%)J;XBYj_@sQP|P+{N10;`J+qoo$>m}t$!kttdF-t2?r3anZ$@82=SXmz5v)f15k z4=J8yr6i*traLCb86j?eTYL;t=LzrWO~YQGwr=bml8`94A3%+i4(7u;$^?=V-@$JFy~!t$@Ux)@Ej`7 z@%;6Y%eOgrPHeg(P7Okp%=Nv7Gj+!E+evxlB+B$4Ktq~Ph~n2T`=wT1bsGPHa%jr( zTqegv%pd^*y8kFrj`4>Pj3xw;F0n%!Bm36 zEpV8ydoE%Y;fy>kQt$v;KVG-B3xy#%8}{-;15h$uv69Gtqs_i~yJkr^iz(kb_-VHz zE9Vd!lr@E_!&-%dW#LE7L0kj6#~K`}`=#7wn&C97_qV0fTVmGM9C*k606FXOs@c_Q zvA^f?efnLPPmZkP{;Oa5=~-`0wQm5?3bGpp-eh*2l3QpD*|6h4V*Vs7BnPJT>S1AO!8IR+Rne2)wbSxM4Fl@Fn zWrPzWh6{JUAK-jH%TI3uDs>Of7;)4$UhrdfC{=0mzFtguCNCgzt_F(Y1Q=1lVw;P` zxPzy(9)IU%!Eopc?Eo>?!_b;EAP^8<(7M@jsul1yNQeTr_h`Gn89qaQHdrGd)LLKK z-;(u2Z5Z#c!XHJ8*JKep${br;UbNyxm*$wtubJO{#=iLP4!cv%OI#u zea}VuF80)TMlZw+BN;untc9BUrEhmQy8XFHytNl=rkF8A7m6V|R{R3il%Fj@(h)ss zgX|v|mgi7#2~A02YRAJk99X~=p^gAf60Fo60UWTU{m|{7g4U0h{?}^&H`Lcuak-*Y zo7t-C=g~w#vrHuw&2vp1COIqkd@qMIbAEV&Vck?!7~}2=aCyJC@+P~( z^WQv1Fy;UJH!EsL$OG-+t3^`TIALd4mo_I_qws5^byOFf&iyvQGc$*3MC1!g#$XxuN6C#%8yb3eD?jJ<;eK?7laqKeuTr+R0qLjv!z<-@Me%Vo>nsKwD27^gB zH&RK@5F(@)ruqnYv^{@9Uzw)dq)xG-ZYb~DYBftjl^ZSq#$9H>I!8mXAwikpjS3Q? z12Ad#f$p`jKFy;V4thpTm2hKkS^{i8ASI91KeTT5DT8Y-C&a+#wTqOEa|={$Xmvl^ zs4(@^56W`;GJl$wW5T3EY&xhXDfmO$}nvJ_i zp0}&aG815G)C(7YYtUACx^&`UVlN|%0d?=DUvI*mV8jCRk9wC% z7u5rqa>`Q&@$g9pjJw0KZF?6-Offc8?C$V z#XR~6S`}=Qjq#pgjS-7Hn6{hcsrw&u z?#&%k^Jvm@wlWnwXy82Stkokcr+50W6)r@cF)XKxUCVuf@Z2JE^J0e48&es%FF)ZO zG{ereG3Cr=TK#s8Fj^tH{;0X^no;fhnkBNoX5jc=JtZ{-)vX;}hYe3d`6T2y-?L1l z!5nFvUNXS2!Yz++5UW_^@z&VQVz~gGxU2Ley-ARjIZ^+%OW6pb6o|k~oJn9fn!g}6 zdcPNSfiM!lfqyS=zAtvMxQJDt;F`5NTjZAM{h@ptpOhcgDQ4TlVzC&a)mrHiHBdF3 zokJOsti6Fb2-Lb7`b-+v=~&Ap=U&H%;mOk7``oU2hJH9@Dv30n?4neGWRKSJcwX}{(sNzs0H(;nhId%0ay5Ns_zLl!dKwUH zI13R$e>~fgQiEWaFX8t=4$sWTXV&Dtm94hE2$qvbuIoa6UIETq=4Oj+%kHx+(b9}w zCAl?K(@Q~kV|iF^KK5=3&ThVa z3RpH3Zshj{YQ&ly<)t)w*$&FAz~qZSN~&)f?BMXa$OKlCN&!i1C)oT=a?=NGIm`V< zk@-``k%>_Su#R#I4=#%TxT0D?!v%Lgf^DXvO)WQMSuPLa8L=;aESCgIb&SE#S*`A) z)dOs;Hv~5%trGZgF4vO!u_OQ9Rq`-m0=?65aMdFPIo=WZP!iqIc_3{qX=Q&g^wwl4 zLsdRZeU|oxF2Yod%4#Cc$9)@S-AhN52_=O|KKqKxBi)@tI)l&w(+wkETLe$F)~kR zwrvrP4&&mab_qG+7R8n~u^=Hls2Sl+sXFnz)3S1b6faSMjsurb zhRM)KmHY|^owH+YZ5cDHmuNE^ayE|6du3F>ofpDEEVFC%(?|vd&yYZiT#PgtbIa#; zc6V0n+p{)EoPEoEQ0zo_E(@>`i*U_xsMeaPzk{jj?V9KR!}xdiB3HDmpu^AyJrOQv z=kwjN->taFJpE*1A|>Oq1eSigFy*i2eO;Aa2c99|s5l?YPS~~3v7pq1xYAW=k($O$NRn5dSZ9uCTMici`8;-Zl!=etIdlL*w z1v5HHe~4>(F$2MpeVw@yqI+p$f|p2tIOL@?y+DVL&}Z*13|S)oMChXgPT$hs`X7rm zBToOv(OJed`M!O4#&Qlq4$%hBB_f^t{fB;Kwhbu}wtxeiji1Kh%g*f|x4pupuSd_?%n#@W{-xxbPxJX)8w_|1f(Lz{jnsud;%_~&w+-T zLNB(mT@*Im6=5>m#11azc-7IIsTqzAaB@@wY)W&53&J zj+17q$_v=gtyq&n~^_i2ltHvS+1 zFDSo!q)^Jm-s=Hhmr+`kk9O^s*Jyat2Us*u18O0?YKGy!;6a&^0Zlbr`WTWi0qJ#% zzrX=Rp9+C*KQP6X4?iMx(5w-U4u&Ss_8Mqa^+W}EfdW4-ak++Yw({HV_)ct_R6&xM zh$I*6!ZA@vGdBQ?u)dSi(^YYY2wgN~Go}~I*Mz3b;dS4vmF0#JvN$?%fTWYf@hA2b z_bXZgB}7B)zIjgqH2Kmu#nhS$0#w*Nc0)t2-AoLNJu?csinYokW?VCOdh21nrM__9 z}%ZyDpD7Ztyt^HkPwY7s#qUXd#)h*id=lx*PUXo9k!rb1GK{XMZ&Djf_y0FAx z7BZp9^Fz&Z7+}7H9h5I<{YBJ zpMO>fw6|1D!;-`5%FOBUrVhxLH(izf11*S{2#l@_`28pkG<#D%!q^Yk(Ekb2N|itb zo*_)<_uz*aXql z3b-F_826B33Hy3cU+^Eiu&=0#NcAZ=`N85?13uVu0{qgu2we(_Xq(oQXo=unFXnrY zYfo{Hfqa9lXob1IlgXIQ2sCztOBQcgIQRGr#oY+ro|kk7YOVq!4RidDJP>SY3Bp>e+JjioB~IP@df1_;U2+zHLqpwy$O z!LQTcW$8}6A!^Vp;K$}5n)%nQ=Sw(~~%@uL(h}y6L%2 zk>JC{+!1Y2>ukabF+-ycdP}o_bPkS`hhPxNqT$`m9_YFz9}D{cwXEywqDR^j^CG*A zq{=iM&yO#d0@w>a-`#H)uXB@{`UdYXOUV;bUtZ$mjC2K=IEo->zJwpCl_mduZ1HT?`QgV+E?GU6ibDBCTeGhm61esiBVV_f< zwG=VtRr-*bwNK%K6q(RY!MFru_OB`&n^fFzf_J z715Bn5mlx(q#fkN@Fvxk?63lnRnoGj$y(;%hD}4B0+x}y{U zD^>ZFOtIEYBSCQeAP$=NnMHgT+Yh@v$nK!KiC=a5UszAjKAR> zl2O{3RnZ^joA`KY5FHkrmJgmOAN^wT-kKGIx9pP9Y>?GAFt1py49&V|*`xrY)Ezz9 z|Do{em&up)@-oBsI~u;7i4z>jvVO1~x+CkDUfiOY9x)cbi6B4HvH749S@7dTbBQGPidnX+vCWY2Z?hH?IQJdDfd z9`@n@RvX*)jonjBCGX7?SbJVnIyGq(4rWLp7_81%F9Hrb?mXOV@;@09u=H+)J5N9B z#%=zccETeyz1%xN&KoLz|HGs_Q4AEw^Q*tFPr!v^m|5O4SIAPjn_B8yse6?|h#aCx zyd(vQ`Or*_`!IW&+1n2W$G_!XdouK%OuYR!1VKWB@w)e`mq*Ko+&S%BaG!8WH|{+z zSJ~<{;WcEBm0HVS!twl|Z`P5}HEen4vuMlfXmlc%N|Sa?37>SQRCF=^;>Tex8Q{R1 zc?I)s4@Ohf=H_J1R5qA!dsk2vL;)E$?gOrs(V~9g?GZpGQi;BJMAKGRCN(M$1Q=H> z{dJNPtthAGWEu2JuBf!MB=PwpZ=(@J#Hzc3Ot3;Dh_OeF!?XNvZF9^v{sf+Q&1I^r z*T8M#L*j(<*sXnkZMe7Sjd7Jh)FV?PDW1a{tsQul2$aYUO_ihOAxDVBu_%RDK2@5X z2f+}_2i_~cV5>nFjCfRg*`pRg^oYVhGXZj0y4ImQ!i zRyQd*Z0+Hf+3CWa6hrS(-o*L--0+2*@`N}6eUgR`LW~lvDXTpm_9K`+1Z;J9MXj=k zF3*^dt1lru@?>Y5S6I#b55(NVhr>Ca9y;$etGCJOTeoSy=EW#=Z}AC^%;OEsa0cT@ z;mAA*bnyF|-}=WAJ!W2SjF`KL9A^ueeieg~TKh^03drps;en2gbJ|pHR3pSm2Qs>w zJE6sK&Dq{+Wh1KKSBnyH*A=}OzRcdsk)zAMSAut=$_E_*FKJ4vvt>fP0CTL>UVal= z-rZ<7z4**yX7ZPUpnvR8I2RB-yKY|EO}uwulDjV$aePr=K+jbvb37hV53KC2asjLY zU1X@0*=cQDF%6^SRK@|xwF7CEWtQX3$M^gAYo;7+qu34}EWWpYl<%Gw(sGS0PRsZT z7rG&?@<}rq`FJgSh-k=B^km;G72e;(JFt%P`#5C>znc|*Tj}5)7q3k3&MAhaz{oNr z^Yx#@e#B*U&|x5_dtiAA_i$pODJX;bm-G?<%G;VIQ7!c-h(l_0@h)Bvv%7N}n!W1F z+G$ofHD;eBCVDW&ulrx-vlbQXE)%X@p_~bB|1;Hd)5Ox67`ADU+M-8zsrA<3(N#-F zZ%D~tK4 zV*6&0kM~yJRb&$CO~#(#5Jx%kgu|aIz8zTWdQm@IR097^>FYwK)}E7pK|bG}qD*?G z^(aHABUS2~%b+n;P)vigj39QO9I;kyGYL&)Bs^afZ!K|URX3!vvqauF<4#JGbBJgt z^hwBA?E{l?7b%Y5vDTn>)^{Hv;k_p3gOLP&ak@nP3s91@9J!ptC#3PM?F4J=Vbx|HY4b;mdZfnP*YOj9lhMJSVJ-0Jppi zebGi$7noY+_S-AVUfq3j;|8ICVe{R}rW)ZIFedc1a@fs~Or=aM1BpA(Pc(4Zo1)C| zg;6sZ)Eyb(#2JpCAU}A6L&igUQ{e5dZ%ou4mISTjyGTQ;*E_hfL*!+BI-gyuBU~$}4Wv*CQDq^2 zz7D#`MR*PmYwN~ItwdE~7y>@4hP&z#zkH(pp<(KAeE0_1kwE1il_2He(Sp}?%2fXm zSKdZSJ|4kx2#qKxw}WU&@^6}O&TRpimR-hk!B`H)RprBfiC)yC)kDi9f_EW>mIwL$ zY9-o;=N}zs+M+l~D}JTE{#ERumIPH5Cwut4W<1ros8VX0!V&F$jXCRwni zd;ZeCQS(?xaazh&Y6$Ww0W3a8taj9RL6&`{8FAoa4-TG=ML&Z_SABsH}@ zdOh(*Q40yRAM%rq zc(;$oP)0Xue6WmS(X>)~u$J|^im3Zdwdnl>KtZk7h3Q;2o$w16T316?#|bL6VA?w? zyk7%W*xBz8BS=vG_*Ytp!;vbxnAnL_2f^v{0hKTKo*52Y50Ck>4oy0;Xo1hTQfZ5nzbmLeu%Mn_66vsY@j-4DGk@X5WM_y6x4AC{yM3%b^(L(lO~wq2%-NuGV<#L*F0lJypzCuT#mlh#O+R__R@$p+a~$6&9pTn@o5z=!NAQ z`<;dVkV!O_N`ErhB{`M5d&M(Ico!ilt{cut?-yUic8HP?(eW!TMoMadRvzi%Z< zp(N;qrGvyiJ#hLJCPp?OzIOShfC*)KkshtTue2Hw)&6sG`9C(40x*ylkGhnnF*H@t z^F9XC%rta*dxsD|0+mzdGdPZE@JWxCJ43*5uXE<^Vs8(TwFUh2tsgyGt@Cr@W{TZYM2d2`0N8x3Awax#E5 z#Gm9FnBl>U+1v#OIFR;Cdat(Y^PRPceD{9y+}L0(g?4})p22$M_~U|bOB^R(JGe@+ zt)}9!tE|HH(ZUw+m$p{RcbxuBHPt`%7!ObS%z=&})FsQQ+27-Hw(cpTx#vGMt{cqL zTKqrL1sldW6wxc(fW3puivMKjn<$Wu$Pf!&2v{@3vZ<~RnDX~LyZ0h_)$ASZ>xdOB z@lrFwyh2~+!rVNR<_04+Hn6o|8&oyIE~^LhsuFia?Y|eoq~^}8RBmXS;TCr-(HC=c z_3@FBd7(BAVuF9wGhT*liy4+jEMB^~z3@8W>}q;LAFZaN(2j8&8ne%6N^%?`zcg{> zm3q**Y9jGgM1OX5si{&z&nKr2JY6hn#xD5#_>v;elf_?*Ysrgp{1DORHPoIl6CsFg z(&|{&-Tz#KD!#0`nbUqcyQLQ>kjs!c9W;KNBoT zFUZ%72%6{TxYB~zyykU1x~cECp;2~UDcrO@rS{!u$*%+}g>3;9`dZbc$2I$dyE8Edm9-#Lp6Bfb zS>DdXrwe9d?DUx2Y$hrrZ3xtZETZ=E^M~9w(ap1;di0KPKk-7e_&rJ^+|Tyl`ee^9 za}?9s4DoW_LGE**-lW*l^J%}5hB3VB`|V7#0=p_uO){@1dORiRRS_KU^Q|XHs>I>C zDaQo~)04}sgBlw2EQIiRTl3wk0!b-Vah%O>L5jLAC=#dcr}bGm-k|7~E%$4OH+P8} zw8LG8Bf8mIZ}ahZ5BTS24@1eX`0ywKr`nvgwfNnU@ecub?MnOaa(AzDJ)E0 zuqGC%h$5AuXsU6&=?SO9Nbhs|=cwp1F-l(H3U&2&2%@3ail%ksIeN7?>L2WGdl4qz zoL*Ld*+(tOflVynEKDvf>`ed{T)Hrd=kxsp_qE5QAhAQ1OQ$!FgnHbD+<8npZTY&B z)@9^EH<6^&K);vJ`6KPH%UWWKSVZIwWT-B{fzcvzJ{3JbCTu3pwnLX7G}PYZAMa%^ z{V_7QdzLQqBYGIqjmsW5<~RihKCLeEltym3EC1jh#OTKuPWey!A8FtM*c5s-LE+MT zAo^~{LwU0P^q1>AP#W?|QKX`wIz+y-WKNuvA7Ex%x(+`dCENm*>aDHbFP0k*{3`vJ zaI`P^7e9CS(V`Gz!92QNcuMBvFnoFcxDGoapd>=;C+si|3H5R!-GT&KANd~K}n(fV>EC*l*F09(@q=iJm;(!Qe{h@ z+ex0h=Or%RzlRIQnD`+QUAhuM@R|TGaco70L*?0QwWt~nvhQ;rBXv82LJqb@bmp{c zO<(mTlf4;|nmkuw(gQqbhEbYx&W4{77XJe&@o5*n??|;8f{n9ZX`Qr8hV+o z3kuY6lt99Z+=!gME`>J_orqOP*^p75TMVoME=DsB|_T$MPu zoci~DYWO~@nR9x4yuIwIQSi=(%Dl7$Tt~0zMJvm|^p)%LW26(10-?emJ1lb`T@b=ej0vX&NrBEXXzH(ROQOjK9ybJB0;1#3n_R<=d_mCD67Q z?mya;GbG7f%O71@JWr9UE_e8zj}^0w|Mtg&ykzfp9=P`K0M z4kyR_gs`Ip zT}WSC4pj3KJlV2Yad`A~hxCJx=ChUQD+NVp?xBJsna6*iMpljxJV48dkA7GR`25aY z5tmbKZ(6o2hVNQ{nlqZBG!MgXXt(T8w%nI+#e@(7FST+?rD;desK%EdI{+gSRnUVt z{_|CE?454l^MK%4=RZan%q9fxJdQ}XEEB<%0~gOf;p+5R4-Se_4DOsO7x?rrm+4J6 z4Ei~B$7#z?II$FK^-NRwCn-o^k%!=jWQ#gExO64Nn2cO@VSnnio?OxihCZu7Gifp}T zDYs$uZGZE~LgK2$e#*=PmkjOKyJ*jHMEdjVeDE8*hW!?##Ejr0aO1RnRbc0LgUlu9 zd&E`MY~|z>N;mK9IVq0E{zV1;f)#D6rksMY#IyH9gvXnXSS;CKS=6j~|7Y_cLE0Db zfs<8CRMjR0*Xpl~Og=-C6v|lBZXM`aW2-KdeXrzJdN>j4LgKk!MGD$na{+`sH$Z@n zs&DboFmIZFEA$-ko)e;^%5lzok9Bk_@eli3Q~J$6eT($crVYDC8m*l(_w7WFlh=af zz=w_hOdoQvA?=+9Z<`P<%qJ2fK#j?m2yaNsp}VkwZl=26@T;e)A4KrhnJna1?O$rj zhNNZ~zq|U7&)Nx|SC3H_KbYYoT}Xv$;t9!+a&qsT+Jz2M4zUEbQaN&LM!07b#90}q zhO)zxFB=nrZ_%Tr0U2c-p6T!2K_6$Hu&$4N@utUlGcSo6BK}nM#=vf6?5#;05j2~$ z?OR3?=<5N_Klv3eJna5<$487b%wF857t9@Gy8eDVs}`X@%(o9XrJT11O*Ep!3QdzF zaYOBV6x<%!8|s)_!#LjRIup4F-c*^e0ye7&SsM&Zr{-kID;E=*cgXicD)N+18z`c% zR>K6D8>>pm6vEQiWoZv*?})IO9LeI#xV}WfEB?tIMrtUg-)@FcMSJrc@B9bSz{dD| zK0>wHe|nR;oxst~^qQ8Aa0}RzEH@Bb=jG#BxDRx!x;t?ILDz;LTG*nq`->bQgu=&) zvYG8h`q!$OYI(*HGXFHg2mMS?^dUb#c-J-^Ly7o4dk8+F11m~U5LeuvhLVEiJ?E?@ zAxX1aHJqfZmHD8N1I_h6!oOj^t?n{}o*7S7Ha%7hg>7PkwPe?{;7ERH3iPV`^4#0o zO_#cj_OlJhJe1Lh(~0Zrus^v5uKwFdo@VX0b`j~Vv@_xPSh=_2_lX+r#K9sxCX+7J zx5OVt;J@kj&ViLjI5ABZ6zM9NSqUwpm7Gz?j}1uYDP)lRYkjsmK&)(+6Qt^5pzdF zVK*3XzEatC=~`E{%-34fe}eU+E;_v;gzw7ON^9tt!bBJ#k|n6C5?SZ7Hvk4nKu8* z7U3{=PwL2sW&yxnb51Dr4CPW1kE^Q9D=cJ44q2b`56$G1?HP?nt_Tu&G3aq4I{#PO8QqBIr4yS%I=;erb}?A8g_;H7Br4>)(_17PsVx;KkT{c zhx*%G2s^kJBXRzu<@BzjpXgyJ>_5;wtvbHA^&$UJ7xL&`Bv}%r-|>s*wZB*nOC87> zxkMCN0Ds4PU-3=iFj<(YQrzpCJj~ zq*|5ho4QrA1N~AK(mQ+T_ZI|ue_ztwoo=v|)5FA|Gi4wu$&F;G0DR2;-^=&dq+ZH{*k`;0n`f%TdkiWi)L z)9q#TMfL(eYYZpv_r9dfKm>yT3~(6BWxe~6i1*?4W!10R>Pu3g^^5Hs&(gV}l%Y7? z9ROwa+0E70rlWjnha(j@ND=LQ_O~6V285u^QU&K%ks77IYn!ps7=^wH@ukbMGZOyU z5kG&L{L7&pwdKB&J;Wh!maBU2AI6 z^R|Kg7cosGae$m$<7g|n>@^OYUcY0PIj>|~YVr*E)+AiP$B6ld)I?$=1FYqKM9ARJ zyOVc7Xa0o`zT5fWgd3%1dqEUKVc?&|yxUQ?5~jk%CaEV|;>6b7v@=uO#Ev{aAOK{5 zCb&MZzS=N`w@!`Yw9eF>_ItOgj`RgR-qu1#)*LThQ#Bh0aP6%HH%m_a8eCvjLmGup zU15!}c=C0&w|;gmpIukk20z|3)(kIbF~9h1Rw7f^n@aNwQ>y}#*|2mZdI%saPcuKV zF7=FX--Dl3tGsCP?*@v)4CynPt81sWGgMiyc~~jA5KSOE&^r=hp1-}rV-w?cYw_GI z0MH@x`xRtD-IHC`=o#_AIOu{_(C%a2!&E&g$&^_&9yW-~ZW#r*?J;qqR+uph7!Cck zTl<96EWnSeN-v&E<%V#0y`lVDC}K~Coz+_mX=t`zSM;GH z(S3Vb9LoglXkO9Nx6$D_9%?pNLrM zq>M?>x3fv!=!vNfVH!1Ze&vGjfIGK4aTl|;#V2nj9Zc$mOW$tM;?_?Z`V=y*_*ZT{T*O-Sa6r*D^>;Q_J2P`(YjZp-%qQqF?{J9J z`;*?AxXOEDG>;k$la6l6BqlT#c=kBe{rLCu3o?J*j);}YV@XsUc_8v(r>TNW1KX|N zTmr1WvBWc~*QNvVx(I?@LEr^%9&4z&M4?e7ooH{DZs8bhBaaV$2egoqz3?p{Lj3qq z%b$s`(@i;t(~S*}2lI9K7AE0$sh<3(s;cS_dK}0+1SLdtf~tI@>Tj63=(1$_D))uh z9|iZx=J@NCK&}-*y4$OzexAH${`Z8NCliTbFE2ZeZ20<@r{yX%)N3c-UlBtLWZac` zSjr>vUXG=jkqQfxG2spGx2*=OFF&yJkv0|UX6|LEjS={jJt1)5hB!&BBzuwO+fEgs zlNl<0XgznJ%!z%BHQnimh4a9K8{B>MSwoa^`F*s_1yXKKVgkfkqgAnApTw;{x52tUcY(r_dOCNH`@Kaa^5dz0j z#6Ye4{Cz7Q&EiQHUxoP|v|;3f{m-U5XX#A9abu$&`oScDuX&@C6fE)+%yo_rHI?)i z1hMbXDOs9$x1P!{?&|%z{SUNcLkcqXvm78lU;+^@^&Kc4y z+pJ0Cz+jH%FO4^0m1}yfQyjb7os0|F<_RIeR!T74lB zo^bN+hJTuIO&Aki#ma5s+eJM#i$m6j4y+5pjG2luR(qaPB*pgubE1tCt%2ZbtI?=3 z=zL~&^N@dVx}w9`S7}D;ZMZW7Q3`&Fih8nT*{5F(nU)RdE5cL20V*k(p7a@J0RuOg zvTxg>f%{kgixIAjRY zUZ+@UKdcES0qpClyKyH;-XlA!&}ug-Gv>5+h_p0p8P)qk6p6bLN){o})^gaa9}cZMQFuoDS2a=J`~HZb-#v!XNTjE&Ut{>=>F=L4YTb?r zq>SpM5*{OU9%fwVYF!}0sb8HC=}$g1wX#ZpwQKA_|76&g@PS^F-Ei$YLtCYxPIkH~ z!HO|0S}vxwklmr5A^u3u%X{w*#&Z?9UWhikjBnek0|9jK()^x}uA!+%9d*GH6ob`(~ag}5RGwXd5rRapRpTs~(f z`FOPUMsyZ4W@C;jfIF!pe4{WMX;v`EJblHkyR*Qx&$Hn{1pvDVK%Gu!qjBFudMYX-|`0=~&1+w;53rZQu1BZyr8=i!QuVzB7>hr%X_BnvYf zhW&v>?7QamnU!Jn+F?f?Rifct$)Iz3W)2_Cl(rT#rN!z#^>5q2^b|X9oxSLWxdSir zfN0gHsQ>WJ@WT@dbsf{>jkwT8B=%Pr`vSSnp*B(%bpSzmZ3=6Mvp zj^**&O5s0!uuc4@F`oE?<-%zvmONZ1T(Y7IB6}|pWo8&mLB1DlTBxs%#6)O~P5cee zlvhU6{)~JR^PRWZ@eC&gc1g^mZKxs)ZjHX!)S`t!bX zFoE_D@;f>H=DjvtOknQ_sk+nqlaWWk#It2M%yovuQ}*c{cjs2Hj=y7PHa8|7n0K6a zG+Daqew07nhwvhTP8~pN_WTs^|GA|G@IZ$Y*zdncuGRZvVSfuaqK$02{J={$@bR~J zq}<0Z>7SmT6Ur%JNmWU4T&JpvWBowkp(gBLPdO(Y_4V}Y@Hjp~zAcVg7jlXNH5@^# z=}#eCSKvUG9m9+h3m==-8Gl)w4M#Cd6nRI=4TeqpUV#5b+BgaQF7g~^!OC}D+l=Sqd#-g{3^6j z_wR)%Arae6(_w)shFu}nvH>3!*NP3S;A-hnm5Ff^^6=fMwKVrG1 zn-gzdh;HabvO$EvLI{WBucnOv^&gNQczs^96W*=AUkL8J_DuCqYr-*XCT=2%Z87+8 zM>bzuv=>*|m!n4SMormFLR-xYW~K)<2N;^x&MvrXW`K%Sxd51C6J{(|tg;d}qlPR8 zc&>JSLRnow7EssQZtl8RE2aBJ9dC!rz#sed%LAI;*BqE9ia7tDc`pr)G3x~n-zSDK z-~^~=Ghub|TI^_|Af0vNiztSQxCagxthl)(O`u&5_O*t__LVX7^w;VI6n4f5j?6-y z*gF&Z{_nF$A7^JklGF+{vBehSGW2p`wYT4JUEwlVF)btYN%#6BUln?|}xF6mKbwuV(={55yAQX)_(q{7U zH75ZqEYCDs+pcluiW(KZhh}&l;8eqLo_Bd{=XyV)K=S9PoyDL`eBIAPuO+Fe^cMUm zt?(s&Sm6w_3yltCd?4fpj;!AGSZAo+KsKB6rS%YWMk`rOE%qONxQ*ZTA|XRrx1s*w zUYVSk&df{Ii9@8C?k)8hQjfP>t^fhyxTc0b7-O~(rGbNC#lb9{j#WKOE!Jc9g}aLL zgu}<&AM!9yOdRM8847c&8uP(6TVf;syeO_Hb!Rda+PHNyxlcZPKtRbMvLoT0Qo zU3;{I7KCXX&Rj?v=^C9FcrkvAoO&H+yHU$^M2dU#O?yr^IJ1`np~{3GUUv8F+RBhz zg8bbdj%%|; zdMt_c$;wMi%3FfO>;vW~v1XHPH z;7R|AVsfzl?aG}#?*-xY#}bZ^3K=^bgc(22ROmd0mxZyl+QGJp#{wjrY6`k`pnKh{ z<+rdo2qn`TeZ)>0}D=VRx9D%X|1!2s($t@Za}r+ndsE*fXz){x);`%*AbUR z`i^Ntu_~vcnd%u*(PLAL??R$Dpdg3*V=jLigI26KVPp)`mzu-q3$+Fq%DSOKudL|H zzCe7flTI(r^4#V+-0pDn0pv3lmW$8m_wwn)LQW|S{k<0lH`GLXVwOE^rKk`VB6hWn z6?A}jS$U4Ev;0LplLlY8O7laN_4x>@0)c9X5mK93=(@Q{IP(|6;!!m0`CuICvqr|9 zYx|XU%9bkfMG`Ig#AI>tXRQmZ_xeR#Y4e-KGy6{E2ns12oD-xhxvKw_dbQEW73Kx! zSZkunJFNJB_>nDtNk3OEJ_;5OSFb>fP;&~8ajSXgm2rclsRT(WzuoDOTMLU%qWl~Q zHCkPU;toN(7$sBbBWl2-nbsNkp*9TD3zqc4qHYcJn;Ixo|Mo8HV1|b{cn0T+LV7O& z{g?ZV;0xUb;6&@wvHaAaq7962|>;OfPhf5WAU26Zf;4-M)Z><9!VuDD{ zh8|~v$Er6;)3O1uy>z~)ux---jEHI#zp|pJ3ex#2FHdd=S{G*AZ+fz=tgA`l&uuLu z>Y~|Sz+tiw8;d6L7O$4i7SjC2wj1~4d71JLSu-FNLb!jl-_p>g7DIp0!=X@X_DOQz z>t+04MVoHov3+%7mZ6B(zetwbBhDr!@=G8w1d)X%z zlJOFcW-B_OX)ULgqRmvL({_;3$U{Qp2WQilMsKw0Q+-_RfNmI~sHts_%8s`yc!)@b z(4>HqJ^j7E4d&5ZLU7mOn1~;5I&9%HA1&uw_qUSloG(NQ@=9+59C#G}18IHv)lk+_ zgXg^i-$Kj%sgJ@|m3#$Ee7UB%R1kyqojN@4=)nXlsHtp6x9rxYfG>uB-ZemeJcKe^ zAq_2tWS2U^U6O9|AIR362#9}>{Q0F7 z@u2+!6D-KI7;CE;w??(@gfqb|qZvr*YrNSgGAcFtD`&NA4p~B(QC$KBjf30eB_+M^ zrxqIN)5Ee%M%e2jsok!9iv>z}x@z0VKeLNP(>PTy}vHLa^5onumM@ ztzM?bpM{%5P<^ZYhUj#7K$-fn%IV`P48g2FpEh^g2u=o*7cK86(qYS-h_QwU?F?q? zd_4Iz`=o?M6umA6u|O((3U!+TC_PeP(q&XC7;A2n=py|d`x6iXhk!_BdH2m zgF5wa-Yu+PaF6Uy&2+>I>Vj;fAK=H70?K5jg^3Ze_31dZ*dfPA0hY@rcXE4>GkspqhBe0;Hkr#+SPn zpTM)iFF~w8_E_q6$*#mznwE=@6ewDQvZk0j-(@Z)IF(IKFz4)zX$Fa9p8f~AVMT)H zWnzh0(Bg!JHf`8zuAx3CpM!(@u)A~ue!7S6*WB{sAXPas@jOyoOXF|VnTx8s8XgSs zs`0Dx`?ZfD+9zPyhGr+t$&C^sR&0rLy4FZ@$O~9>58T4X)@*QQx{|sWOrVh2AV6?& zE{<=xk`xMI*l9}VJZc8RF~)9a&=637F4rxS^J-aFE;<>E zL}kz(Ux}*HlQn#~`&CMzH6hy?>n2GnbCwt2Ail@zu`$V$Qsr)Q+Rn5gn)v;FgtP|M zpLrKnrJWDI+e5#JKoFDfyo0KaEm(d#DhndZf9iTsp=(E3WuJgyP}n`dY1lDKrJRSJo9@(58f~; zgmLre!X;}&zuS}&qGl{vD*Iv6nPtgPD>DqCp~l+hLTrx(*-OC18z{rXnQ;o9OU82` zg1v|b(Ei^w&EEW4OkuWvO(SZnu41TpGhVR`2+!L&>uimN3;^otdxzJR=e|{1xKUKE zSK+D8yPGp0Dr)Qyh4o@3Rph(;gcawYE6c5tzkw$Dm7Ww-EydjI_iL{J3$9`wBds52bahuK3l@;ixRd;A)|a`^w1Cb`;MvU!lSB+N5*QE#fb^;#N`b53DlWUwr$HRn)W9uGinVN&FG7p_{YRZc8iWe5Z zhW0aF436ruF*1pi3*g8!kayO#PdSggOb&WrW|ti|(WyY%MigWe~8{}aaRGfphbMIqR6&@xJ&1})*9kaIua5X&?IfWz%gt(G)muoI4u#^{hg$<;`P{fn+BZ{+Lf^+lCM;%bE(UA3M~vfMmodp z7c(wO*|cabj=5xQM6H){7QgyU@!!(SK7|Q5dsy@F?9yc5Bo%%PuWsY*8Ql30{k2Vp zLLuNDTVm_ST^D9oN{xt~P(QTW7u@S0)T+@+w^qT=P+OWR8KE4GB;}ta8y$NQYm7TO z%ai%VkWmlfZuc^brVQ)mA9-SUkZ8eb!7(a#JUA(Ea*nQqbO2O5Pw3Bj-?V*xiZt9U zR^YlW30t+M&X?Pjs2G`q6YSPw4Fg+! zSr&@_L4aX{k;Nt&cf5@K<&osBc@$MJHZy5IX%Y;*Va#1woYXujgYGoxWDzTmJkHWGO`& zd5z&N3+XXw-|iH!sVJ4Y9nJS1$bi^fr)oxex8^-}O+4!yYYntFu8s(3C&Eroy6Tda z#7!V?h>SN}AoPssj6zsE)JX5aQ9t&x)^1!sg2|f?T_pxt>bxFbwc5GT_~1R+Z4R}r ze*1EiD9>|uz83&G{EK^GwX_X4sdjB{x)Td|w6f z?b(27fl99?Z3gq^AiCamNyJ1Vo~qy&SIfwkZ~_qq3PABW2yNSU#!2@BdN;^Jp`It^(dvfMzyj~tGhys^ra2Fc@Y zNllE+3{I2LYOGsRpF@|b*$WJWOj2jV|O%1#ndpd<5QUjXf=f`CkSj*E}RzQ%{;453`9yA&dKHQeV6 zhj|8sQmC5shDSUIuMHJ|CH5{KhBk7xfz*~88fgOS6>2>NvNjUMpAy;F!8pre7zyjw zoX)*v2|>z8&CGH8A%|HsF>1y6uP{|8b5)Kn(NWyBHKYdJZ>TdWu^V}jtP<06{^0$H zp=jINb{ZH~h>c!AD=lEEg7z!3o`667NcF#iKIPd`vSiSg-$-Q|KHFJt?~g& z9>ZjEU*z#kCE~U<7eegg!xE0}c7XQ(`2H@h*fgJL<3CUeg!PiXt0nZ~HB9uL08O~* z1qK$|%>4T+UaUK__O^xA+5XTcH?eFeu};bPTz5O8eCd)0uym?~+EXaE{ub@wuhnC- z3gKhZLI@!Y%OIpita?uOrYDmzxjcu^8b7XZ)(X{K38BaCckJDIxzog<$0i0{2jF7W8plOh zTZqoN?~=RURxG|n;C=Ljz0jy42o7(3b3`vwF;)C0b>l8?#?}(n_3s7UZ$qgA4ae0s zy!oObQc>hB05noGs`;Svwp&?0P6VmVD=u75HM$Q#SBsPgZ)zA8SR4?a3u~vJ?>oxGnJ78e<9*eGw3~z@C5W_>&I8C^ z$02npgghteg!Hj?;c>Q>(Hy1CL8NOc_JXk8FL&G3{H#U3c74sf<-8kuy!$=f zWwqT(j}=Gy6?t$zfOiiz*%1?|Qu^rjz@D#qnO_EwC{5aSioa9NBs%G)!@wQSW}0dF zzWQ8f``(=qH=ugk``tvsOZlnHyokO@<-Q;q;L^~|y6jNHdl|dpwISv^8oVa6`?OA+ z`4NuPbdXZ@bmK}Zyib5?I7t1KLpzOQy#tp--A_Iu9jQ0^@31c0Ss`BHSQi7tvVGI>dIpgNT}({%bT#zhEv=*D<#?C{|t0u zMDjf!dy;t_A+Z^FJ%h5^)5>+**&5}5pLtsC-z}E|xPpUUR#~;GOQ;9u{obq7NDN4J zjh8wIIPznR9vRjiuAy0b?atF@^ioYu#%Sw<-{0HiR6J7#@x`&*DgnD% zM0NdSARqnS^VB<{5y1l6aG5tdkCcdI@0u}K9W*9cE&1J+tM?6!Q0n*WVmkO`$uaPw zF-Yz*jD>Jc*fe1n&` z?6y)X2%C;#ImAC!EimSht@tC$#27YaW+s0SjFo}uDzv7aWh}|ncuI)o@tZ=5!t@Ol zaspk>YqA;0D`B68zOhj60RdufKNS`eFkdi;*<1=tGb-?m`q6#yEnct0B>FuRkFR{0 zMMZ>IDp-nO4Uu-q5vmrxN*dp6y1IWag+LGfaemK{R+;IHC`R|5xw}ViIHM|t7ppnd zUvtTeDj$9rDL{N(0sXClVItw=>wJC{@g^1JQ%v?i7>bU*QqO8ehuMI`%0*$b- zf}mquV?&UL!KwT*L+xe~RYmuCD*Z*- zG~07z`Y{hjrFejMAQFaSdE1nPPWGuYN^W7X3!_j;_ZzPONPAwUEkvicBLuI-3eI{N zVS$KVU~K7+^j4tpV_iZVmTCG|&uFv*tf&|F&y{>zxlEsFsGnR#2A+He4qhI9*{|+d zcfS!8=|=A!E8Aud{;N*PIx2dG&}W!>LAc8iQ92#Fi-+aL-aae!N&W|LAIYeN|LF@F zcYo)w`$DZBFW5AVquD~AylYY&pI+JV!5)WipLZSqQ+@@|x6g|%TtbX3M0FA)2AGea z1<_)+wIGfLst0QQr%_sIKEEh#xM73@-ArWHaEcalA+DyjmIitBcNdn$Uxp?888|w$hx~$I% zl&KNV6jqykU_pE+RM|PQ^FxqG{!J3f`uG18mUaI zW|ByF-)euW#VwY^4&Mgo#%AA58S?GxFO6^g#8L~0b@a~MC)0h{6`6d=b`j+%3jfOa z66HUOU6bI~XVkihy6Di7NIHn*{sRO0!_UAJ<@=lv*^P2c?K3TvgO(niOLBBHE6t_~ z<^EGdz?ZY_Gnz3STP?kwZ&aGQyoE$E3`|k@=`-ymhv?Je(V)X4N|dfVn!Z|L+yPHs zXiD+cphQ<7pA(ihkdth#~c`03n(WvPhjUa78+Ar=naJ210*!$>^fNvlBR6mlb2aA#3Bs4HEHjNeQ1?PmCcSA_n5lY9M zNXtrlgt8;CCEJa;OureL0Kbs_UE{}fZy5MBjKET8{#f{qSjyj`<;-G+;!7_t7*CXAeYf={s`MA(wo3_@<7~i$ zEp90TZe{=s+&1if&_Qc7cWbPZm1R&iAa85J`^>T{B;nhfJ!?q>$EJ%n8L08%>%Z0c zV0+r=I|m|8LETy^SmGwmr~;b>`&4G2iFbe)jMJKN{^{Z!R zwS=rh+iQpy86_Dh$qmokjZ33Zg)EZ&Bz2-xs%im+j~EzEH)15QZ=4B#3l8%w7a2B? zfVD~zXNFxqfLS}wG%x9K<>d0z3iZg1mGQXGkW^;54b3jE4us0nysqCpb@&+%=6j;? z4y=|`cS;QD?}rQ}PpGBY)Rp6uIC=ZjQl3UdB^NHWIO}D1P;xuKb@N5lz4U*?jM3tm zujyNC*e#yS>rsST7X13z^dw&4&G?`QBc26}dzjQurk~B1`MLn?i}Nz(hcl%g4K@2k(EQkH^^L#VaFKZ<#;0HmQl!lR~ps z1s)&Hsn*%=QR4_v*6}h<73i*2{1yZT*RL5rmfkV>)>31KHU75QV*^hvlOi$*cKUAq ztyCkP5Cv@Sli+^%dbsg6c_F?@d24q^^1~$Zpv&P`?_cjURbASI4Bo!WWyI^CvtR86Z)GA6y<>D{#j7we-P|q}31cEpMeU zcwK<5VB0Q<&l3OrhuX776q?z-@ki)mpEKfZw0)=f3qjw3MOEyCg$b*&)I|5Vf09nR z6C=_;rS?JHO*^m0mpElkFZ^yuYs@`67xqI+a_rMg-Cp6HabY3vxhJQzUJxM)dPvExs6EfQ6U)kFstPpAYWu!MYy`Z$Bh)%V@Y_^DNwQ`?o| zm^nagDCqt$lVA6n0;5(g(_B8gYGFRY^DUg&{!cZIqJNsjC4N3{!0^K*yal- z=nrXUDNEB2A!%vY->HSyV9!|a6r|JB>p@!sxBjXJe_Pe54g2EW6@Rzed}u?;&Q^n0 zD4Pkt2F1-lz>OVil}?^H%}Ff2DJ=hTUq!mTC51yC*u9G$3?I2fK#GlP$P)$fT^ZU0 zs8wrbYQ~(e;^w{IWmtb0=i=LH#d)e3j}t+FGMsuCNxa`8`y;A_Az`1p?Ys}|Ea(NU zf3L>_r9&GDu6o)?xE4b7m9Ph)j9ln2Wmt1gH$iZ zEIB~iebjVROGKl2GDTEhC;cxp{pyyNGv<^7(uVF30dIxtt6O4SVOXej|E{L&qR5=Ai?M)0s1!+nbT2}DngXh`kEnX%1wwxPLQeY`r=r;O zf4tTLU**YvY=Z}5F>mkT#E0lY(@+;@EvXF3Pq2KQ=Rb)2WXTi$1Ca&=z@%}4Gq8$p z_*xdo*$e&mSxhlUTZlza|j~(XxE`^pJU$WY( zZ}?Z$%6uW(@tWHInj!|$H}e~6Gm4Xx(ZdhAcIP<~)mcSH`pDVF;aO1(1(}w$C!Sdm zo3;8`-+}UcCIv_u)C;ut4RKYyBS@a+^!%9jj6-8+Eo(!vS?9??$j@pX45LAB7xd=6 zrsCEGurC{=NGvl#A{*ak=$O^XC8)R#)yLyM@h2L*#^5k48yyUox7k$7s4GYcJW)G^ z4U$u}W40v4U?Tkp)lUXST);ZyJ$;HchQ0djjsSTBnfR86-OJVS2Hvrxh0y}ZzvSvT zMUoW32Y{%0!igGXZQ+a~C#R1N74Lc(U$3b&5@qHGjQH@XD91e{Z>6E!Nul zWZsRS2``Lml#fDvF;Y-X5$q;fHnL4Zit`Nq-lJ%!(Zw{kFy`;5h8qBSj&yCAa(NgDX)Uc}7Q>1{S@wjOWT6c2=l81E z@8%DU6 zmanU8h%a{yv0wD>y@OT^34x{KR1#f2o+&M%nbl>^Eh_SqS}@pInsPdssz7_2P!E_L z#qSNQZDg`@D%Br^kuTWNf}Fq*@K?Zv^9U~rOol%c4FK$WTeLp2*(G7^ogrNt9(La4 z2-JTrqkiM!x`L=^DQ{)FY&|*2w;q!*^ziURMGlV*q$Xw)a%lrPIf7qOauE6!wX385 zK<_=oTg*S}L7OQ>*Usm7Ue6^Tot-NowN*m3bQsu5Pmvbrv-8pT^g>ptRN{Ak7)k2d zE*HPJ+QFU-$8*(D{Tk4a2S!(nPBg${LcuP15}oE~gS=QoTY?LW;C&zaH=dJHaG>-g zcLtFf(?8hcLsFoz632+{whDQzVn-;wq^t(#B?c_~+}I4=^1>GS`bB;H&%Hin?PwQh z?gfy^$lXRzw?v@JTddZ+^z2I#yHvwkZh8*wVmxtZE@3a*iEkZvB&SMjOPC>GRMg5wSxsG3L-{BiNw=dH6 zU9pLeKeB@Yr{pm_N$R$f6Y=T#bIMWxKI-X1EC)4ZQQhpVGU z{Hz+9mN=raA%wItf9J*N#)QZAkUI~j7F(+9OrQjg;u^$+$vKSo&915}G!&Z%%J&F~ zM>P=!zMDu2{op4Afuxsy1jug;a!TR$~K(Q7FPeR_Q-ylu3F{kM3NVQG#(&V zWiRY|vnl#KraA{d_*U7mt(b4AG#Jvy_|C)Ld_u&%U6^Ecn{=uImN=c>ul+6ckV2X= z3ai{+x~AywJL^I|d}l;ZV_W*VkstV@&$~MFBP1_}L&1uqbR^iFUpq3_=m$P|`q?3c zU+(dRdVr^K(nb#whTZXY-?_ z^>F@^WGeeK`sNBZ%UBTy0<}co)<4=E5O|_Ub)-7!f0~kQFL#3EC3E!4i&UgIoHB&r zP8PkFM#9;$>-L|0Mu!ZUaXU5FLF0WL8fQaQem718*HiCBJQhZVPN(V2eRI+V8LWzB4~ue{GPo z-@*AiJ!GAtVejmEOUCgbnwpq=@3J<>hke=F%96PNf zuJ^vhAB$Bqk2#8w+6>c~l;D>BD%}#LprpZX;|tbvyFc9ecY$9>VRQekLIc00ecT)>WanJtt0%3hoxCZZNQB?@ z1-QOjSuOV&b>P7UWHsxYxO~HSs%+OEA8$e4w+M?r-#5vw`?-n};lo}`>6RzzfEpjC z+`o$8Q#>j>XxN?1f}~%@PkP%j-mHPaoZy2lkdj6irxJ!BSpf94UN|h$f8yY%jq^$O z+mZuLkq{1?wEl-?q8D$^MQ)nU2nvGxWo~6=?M?FTy(>`N?;u53fr!s!xiXzk>R>gV zEv+zwM6Atps)^%$$v1l6uW%oxJ2<`#Pn}|cFkVNkVy&N_dT{Il5eg<$TWqUG<}M4z zPN^&PGeTD|I?%>UH(C6R{@h2mpc)V9Ep#%K!hGqn!mc99c70Id8|6C|E!yue4sCy?(6c^4@EgCL$kc$7ln&%L8(vvTMO&(I;1;U_h zKHxuyE*wG`;Y6X-uyX%goq7eT>*D;?N&6{_J^1XOJzo2)wn1X8YX>va{W?=V z(={bMmP@<)0R<6Ge174t-n`=8Mwk3&lkpl6ml*7ZaSE#$hXKUIhjl@kDM6P2eC-J@ z(L1k>rwGy$o|4Fd;^Yq;T-y^eFYRK;W+)eoEDJtTQ&qx}e8954lR4h(tN>u2(4F7{ zNMPlLj9>j;RCQLXdqQA$+njVCW*(=D_88Y#7EtfBs zzskV1X>EOP?>?Yuq3=j^O7c?N@(Zyi8=H4gX7ITf(FeDCX0>ni2OV>EnhQxdZR^IH zMh3D9fFE9CSjNgd?7Ldas@3%8ee`g&L}NuBrBG6|`{0S@gEwhGzP&!?CcQTd zhisg9`7M=h@3Zh0g^*`draHO@Y1=U!>E3YtTND8eVI0DW6-I z8R+F7D@>X*+s^E;AVkLPAZ74VJKcwuQ93yI4u$p9z2#OYXO-anD+~`K)_p;x)BfjD zo7Yy;8_dP((i*XeNmO2=dO?!>lfLS~32UykLR+hnQ*-sf<4ox6558an7u(jR-^+n_ zVnpqA#l4he>lyg=T%l4W7zc5#KY;vHO`NhzVf(;d=J5wTJoU0|R+d+~ugD^fkk1@O zr22erT6}uit`I<9_#F?Cd3b{G?k?kppCOqJ8_8kX`EkR4y+IoN5VhC--1P;sCCSvz z@_|%*0NXTGEEl3Mygqi2I%b`-gc$SKB(Gyx2*l-?Z!wrIH#s+7i&3 zy*%%9?8i}aCbP$NcetoyUZOTJdLLH{1?*fS9cE`tYd6oMuWXeUSVwI!5*E|t^4d?^~ zJ5@`cW|+O^)sWA09IhOORQrrUTox*o3Pj>5X?1>-O3!I&oFJWP$xvjd$KjKME*+(I z544Z-4C{1%?J_r;^~o|-7-zbWdH z>GzXtKB{IxI)_ZK7s7xREa;X$kd$t_MHzBnR$RU#glBBkV7Th{{W>#UH z(q-sX>Q!o(C{$|s8>f)!orS4P=N?PK=_$kN1&1p>lTQl9D)p-euWchZ>3`CP`0VyR z|L!@|&`UZ;%GTjD{gcxo<}P`Z;`lP1V-4}~0bhh*cJYzWol(mtg+p6%L!~m~1Wlm@{#^5AH&v-N+V!?!0$D#zSX5&m9@p3qob zJ0(U&609pUQKc72MVk}WE@FRIkl`dV?-ag)lofCMJ^y-!fEI*CAMNJv(uZ)&-jr=5 z9P&25y@ufwtPANFarZ}vk$T8X?W@t~ik;AL4iMo$Cj7p?pnM4Sr2NhKjMYP@^v}@x z*&4xXIw7(v5b`MzPI;aDV>~P*9O-=9q?x z!Z)6r&$$f3SH2S<{@xe8@!F%|+g1m~wvo<`!@WVm!yreJbnMuejFE{3cjW)-sC8_0 z5Ym`oNS$q>n}ht~enB_WAb*UwKsQ2JG;WuaozJ`%Zb+J z`E2CXa5}-IN0SyjU>e#-X5msaWg}PBFK0d4n3O_!aGypON%xS&A&Ex0dM9rok&5Rfysw)vVk@;l6u#ayU+N@tOY!Y|q!&|Z^`a8y$oP5<6 znY~FGG&JpFDNLH(@I8m$q4J{ZCr^P+bP(F&hpTr2qDZ&&ronm2tZZt%e49K|C#Jd1 zq8KPoFyd_)xr5C+$DjIPjccR%Bzce569S~^aiB+`U3vDYD`MTV0|K30U;!aZDDr9a zh3kI4L%C@Q&Bh&^He+oL_Al@9tFF@EsiGR*;mwew0AqT5K>Gi5clN6_PBaA_?6Fni z^>_RT(}P)t*Xnx*!M9%>$F_2f4#B+TMB6O-i_*APB%sBXUHn2V%~6QH34VSpcq)X+ zA^{0|ZD#Qw$UJ|k|F6p8)&ga>Y;}28@+Oq%s~4}z?_rv_&6>C@4R=B;Cl5u;CfcdI zfn#rfTl@VcYKW!?l-KAdiNd;UGk)t}O{SlA!MkP@BlB~7z^0e!(lO5~+w?2hQ^a!q zy=`WD5mWGt7@4>3&AlWtDg7hnrRj^t=GJ*-aXK*SBZpV-c&O9E-u0{Az+%^fj{RDT0$=;^OOfna2l?l#gN?d{SD+OzrV( zmZIOmt4fIcy#FTbAzyb>UWVdCWwu1=5%+7J>5Nn&OzN`f<-9w1+5ec7TbKRDPHw=mM} z+NTZL8Lt!Su#&HAt^E4>TY%4uu)6ALq+u*%>=-8QSJYIX$6g&&M~N2{8a&133DDpJ z(^`nWQ2S$!9A#S^uD`_I8Gf(bkXRXn3y{mkbl~C~A#ZG#y?!29tH|I4* zNJwyrg{_C#VR>r?qIpZ=S?1rhcxJDrm-kL=vwsR8)XV3^Sl_Pz(BxO8fi5g;r(Prk z`7pS80$7Fh2St+(Y@DTbxaID_c-_0Vi>XAcFZYdH#l$DXNN?>AvDjgsX84kp z&BgGU_N?b4UL^dnZ_-QSY`p_Jj<1)c#}|01C<7X&Z$V=wTK*04DKyGs{3_3ZQ+LaL zaZ;hh^K%P(kX6Asu zZwt}fmUUm?mieNr;G*w1a=irV0d4kKrliuY$bWt|riF;}OxpKsYG6Ud!S=*KxftDxfrsg!bG>y%d0m|~1a8QAUr>!Ro{~dj&#d|z3Um|? zk-CHoE{ys`ttt%lyRoooAM?-4$gOh+q|U#}e*`g>epQ(GXj<&d z{@OLK^RKF5!0EzH!oSyI;Ds0j7sRbX^F-<;8x6vp12?9V78(`Fr z$*`sMA@f?X#+^27orL4Q!0JZ-xl(=$cT_|@6&-GWjuG@sJ|s5XBa{^lze%D?$A}eI zKmLXHVLP2ehWuFCR84CBJyV%$!WIHovZbZuG>MjBL6Boka(xR;(6g2VPz!)Sw@ZFX zVKL1uid0`_Y2T7YLju+0x(UZ0#!Nb03;F#Aaz88^$bSo~)zXMuO}JQ>Qh;2sSzt&N zW>DbI+zySI5i}e!Giu2|ndSe#d%9g``^Ql7PAAAB9m5hev`D1;l(c=X3Lq73a`el{ zi~QSns}pjNo6g7=7%hucoLm*-TgrAe-@79)!Q(1+&j((vdb+v@(^nHGt@WLT&2C4d zt_YTl=sUQhBLz#Hg~NKHv}R79e87!vrd4E+YnD`=zZmhHm*!llQK?Z`5aP!=1_waq znh_+|@9q0(pB9cIBim>~+aov?Yef~Szivovz^MK20zT%mDP3X&-&9!%W??Un zts!8%f3A}E!{&zT-cNi`p@bHyl#c3&H8Ia|D|5^c%0ezl@G6$Lulwz1G`n-z37!Lz zvg?cXrE|6Z)lA(i_SK^4zh6t)MKLBHHb2}2Aobg-=fYDcKZG;}5RZn0f<^l@q9su{ zmvhpy-)mb`zi2jegnN^735x!x6AQCZwxi&S$4-lT<9A7hQvGTP3Jh|AL9ECC|8oXu5FbF#ecL}n-{AN}JWdK! z+PcuDo?I&*PAB38S#IuF<)D|u52{gKn1<$3E}F_A^W~T@FBkDV*PE_B%+I>fs_Aw+ zs>UXceWOzOfP1d3SXhK)l>EMMW4ex_*v&}+llEuOlV&UF$q<2p0O-5laagw+Ya}T{ zY0Fokbo7BV;g_(#=_|;Dz|$QmZ@l^rA?$o})ARD03OVhUnuR>EDbM!7WtnnU@T(}i zls)%Zn+6a17FWEYNFApNszN1ZNpds|JnIDWyf-X%L$qHba>=mcSq44}O0^7(Yt2fF zC5@h`9&C0e-Ln7b<TZvc{>4N%yV*&BDyg8p1_?KfC z)jqBKp!SlS*6gSFy2d&>cCgY;J|i>WC=oCQ`OytY7QQPu5T@Z3`xS2}AD%4F?*AVM zXz>jiJd`o6oSsREVT)Vtkp$O3@r%-&8){K>3Qx$tTT4=gk={D7yuH?!V~fMUA)RGif>GWvL2ed$cuwT(dI; z5VXjU8^4&*iOgq@-21Z;2=@CbNx-bXpi-x-*q(UXaYwnqeJ)1gqffV!&^E)@e2s&s zk<6mQcUYpm?NvrgHZ`RG;zC^EsVI~1%}SvwIQ^0*Hhq;l>0KcFOV*55-};ZpJ~r6x z_q;5jmMGeOH|W)jJj~Rj{}BCkPJk3bc!>?$13`vR;kvfLX; zD!uOO(O&z56=FfqB`K|^1b-aXdKCv5qXVEzx0jv=3w}d=Yo@0=m5tS2CW&&ev3PAU zHlJ@nNA9Et{P0nhy!~M}yaFD*GBP;CzlM0*mbmcC$FcL} zJilR419_nzl$pKh9L^`+?86|fXD)5cQIfQp1623bX%X#0CZXzl4k|6qsSvjHbzt@a z+%wKb`hCfN9NF!6UHaNthSTUCF2qbUgokmrWY|a7OD873B@#h@Jce-#Q`|~SE!a-( zUmwe&lIUT~%IEZ?f#$dG+=YsNqc==yO#=$d+izof@kD6G>f=s#Pmwy;Hrf`Ap`M}X z7>UkJCNgq3l}>;IuA}K&50|uhAv?IFR{HPZMFu^TM(T8Bb7FMfUF~D)PU(+@gmnCm z1lxL5sqaVoxuzS?y;9u4{c()@Z+vg=;J7){+5cehfg|%i%b&-{XAH00gI?IM4ua|N zgDrJhz(3w-ulMkw6l?X$Kmtz}hI_wt8cxY;m7?RYxl8pqbxOOGuQ1{$Nz)|LLVn#G z=!YblGd#XqQat95*Fh3+x`N9F_FbKU3545DjGIh0?a=J`DG3wl`2 z2HOa!TMa*L_I_J=<&nnFJc?rO0ah6{rSclymoGd-8JZu>xH1hU4_#|3E&OvK%pNMCJp9m;4;%ziw4`stW7;t`^-1x50?(ERTi%(r z9+n7JD&#l4v{cFKai@{x)2nMt39FCl89Q|NFG|YXT!@B6JV9!4@_`! zLG6oBr2t(PLnA_sXgHvF_ik8SFmJahiPZv~mZo(>I9l{?W%oAAQ@h}bVe_j%~MxYzp${oIj_@sC>+O1Ml6oMM&f5keL;1b9K{ABhoqIJUfR zsI=KTpDRk`DzeEuAlhhF{(^%e-5Z7H-hTK!&E=ptB?_%=+#GT_T-n^g=NtAvb>M5^ zPYu@RU!o4c_V>*$+)@9GTz4@rxD%vbsLkisE%tcW(W~6P zCr{An!+GOrwvq~5oM_@T`hNyG!56-s=$+ajJxqsN27{%1y5pbv&OB$Y6!p(8$G!IW9NO9cy`1fcZ7ULr)U)S>AhSaLN;Yx0{%>}MaT9x zNEH^m?u-~t&YI_pTNc16tTS`ovLF4s*b@BoB(yVXp-SdI5Nz2%W0^b`VQ7EexH0hS zrF_F=Lx!8GoBTN!2ipUO3~{-wv!yLSVQH-@iY(WswT>-C(Z5|od?6i-CO4RiCKOt; z$CD7aYgXZQvk3WE@jlCr(mOT?KM3=-`|jODn9oy*Ua3@~Y!vZaX#Jgr!3kyx^-OJ2 zbM8%H{SO{uoI& zwMfW0RGd%i8_mC{hi*~iXot~Bgfm2F1R$Mpn{RI7bKvys*&ioMt7D}q%E%>Zsr~~6 zkB;6?uM%wq+Rt9RpF6R7^1+H9w^(UZbnr-4y1oL~7iMr6A?;o$Uvc{>d~rJdX{MsU z%Op%e#cLJf%4py9wcP3JE(0w#hf4kDZWfCZimF(AZIBYsz@`T=1k0S7v>>z%v~-GP z$t9GLGHJa%?+smF^OJv60!4=vBOgW2l8&$2pVPWe8YC^3ek&M!wl1*gpEI}(1ea+} z7$rdp^X2`&j5AkhWAiCFPdU@?#yVvB6phAI)b*6Lo6nI3?X>%0o9fZ|Oy`<_i`~pZ z4=G&Zi?hE#ID0?;>#S~S6Z?(VI%l!;Iw8`4Lw|8lkJP1-o}hctj09iMlJ2Y@DS-yO zdj1b_`M;Pm#_A822T6wVLK=!S0&P;_H;|G8gXC}430l&i!aGu&3W%(SSzld}fH#2tKjSA=> z7kJEb=22Rl@n^&o1TP-A+%}BYm{nO7lIBZ5bkz0rPnkWxEj&X$ewZ?{Y`!GDjZx#V zNTp3o3|tG-CR;DZ?mj5{IHJ|SfBEc&gn(Z~pItf0TSR~$3{$oAF7;yBAoS4c9ShwB zQe)9(QTr<%hU^D{f1Tow6Lr5RT>GAK?%jIv?}TIE|EYC5_Sfrh)wwgvSYETb(VD9$ z_oFmbh&m)N_*1*8oLrjp3UInipjP?c$CvPE&=XtCdP0WTQ0UTAYtQqxmI~*aT3WG# z={EX8l8b1;zYzLa>`BP_#uvf|Z~V2DG5ckEhsA%dU_7|L9W--w&>%QoeW(6)4PrO> zu(n~+PdzB%c%$hEvs*m5G4#mlv1NI0u?cx1_SfV>cYP!j+J>1UyO zOkE!8_Bn{2Y7!Y;GuoKpk>CoVF8e-TINGgGz$keQ^Uj}F$?8sVYhI*0P&`;en7654 zxD5_vnfVU;ohOMkOpU|?YG~@Sua46dBvnoI6a5zwoB4f=T@#suIP(<1o(QXUhQ2hM z6x$p2cD*WvrJReNNFzEZ&-tCU!`t{yJy9qESo3qgcJR^RzF3@>kEdXfH*O*%`13_e z`V{K~Nqpks3S=PSE;#J17iNe_>gbBq%WyX&$tBeTvu|;4g`ah)57f0%k34H^tu#=2 z|NKxe%w}?8hUMCrM|-Op*@=2QG}egZg~y(E)2EmpvO+ z7C*w6VM-14BBjUAU6rqCZ2}bXXH3IdR61rGfoQ1N*!jgVi4lC8c4#W+c`Qa)XkGNK zpGL#uqDn&Gaoa3^js2`IKKfj@>tNkP@E5;{mO2sI?h+uC)pd(-1whf$qoDy^BP>Bfa-R8nUflX-)tq zK*`1afPdb;tlK-sL9eccEU&J79{F>&tY-+c0XlwtF5>Tx4Y@Ihg?}_1bxDKiib?e2 z23nNWTm2ONn7qITIm9bn&b14rFAO}u^oT++=7n&mLpG#Osa0&9SPX{R0+vd zf3G$1z9~;A@L#c`kQ7!g)(uSLrT&6Ms5d7)4w*Z*W1?Z9^}~XqmF5VQK(kRX(Jhy) z%Gf3qY0zJXf`i&~nx&;Jk}OFO`x?Wk?cr+0d5Pag5lTaC?3%Tq#Ng{-#4n#W^^rms z$I2h~Csrg!6qciZiT(%bQt6s`fM(!Gp?>_OGdl<7r^r|BN5&PMMenV%(C<^?YYs_YedWP@tv8SN z8?4wN0&s|Pt1e$>ETgOW$T}c4;*UH>ybtP4XN{5z$9Tg7_65rQj3YGy9=3r|#q;vk z%$`!Oeo?P*99pbxl-uloAo!uxc5b*Soz0#oG%-GMilT^hmqwIJqeIfKU#gk#OZ8e! z>Q_Pm4-ad1&fhF18h!4PQqM>|q7_wtZW%=$ZEj#Ov*swi73IQEmAK83M*btuAcX9c zWe`X!t?F2n%y7Nxb1dR4ZuwVKAqH$y=eVvR!W+-$#N1E!_toRSY1a*g_=`pHya><3+cpNmA^088iz(|R^1X(btDT7P*1WxZTy$@t|D<*jQ zxen@j4sxkijC&|zIk`p z_ZY<&RZs_!OOndmD~>_18&oI`ON(LlHkxcAL1OuG*#ujNZyX*uhTU_UM5jp40Od|v zLX9x{AB~rKr@^xM6O4Y_E>F;Q)k}QIP(&gC&?SceDj?hTfrF72j{v{GFvTQQi=~EF zLQBmY`K+nLTwr8FR~1*?y&d))MGy0CIXBZOPR?(?7t=ZK4GxM`ynVY&kQqd| zycSVxMA@GBfO7-6HxHK* z699Q}5N4UMs#9{4X)Om!nX*EjiTjCgsG+}PMZSruM_=pkEh>&d&Uw>QnvnelfEsJI0Gay}?s-98w535rEs^Hr9M@KUm)3 zw3H&hoxs+pXKGxB9j}pMnz<}M-SYdiR_F@-{f3&X;eKdeJ5=e&S$D{#~Ajv;lZe6Y-#g|BTf2NX7fF=T;AUXSPLEK79a zW;(CF_a&}ANugjG*7i%$TIb)5>6bC!p7gNMo}5$O;3(7}!GGq!Qx}?Tz}krs7bkPI ztv|b9jL~%G-zx*BpgyR?XD`dpV#my-p_!dOoWovxX`AZWQ-mh3PR_f|adhH6yU@L+ z$I6&nIL|gcGnn#bw`_X52mu>XXT2tKMk*J}8={|M5ZQ?exH5?EeqW6fv|WIeZDz3UJOW zOo14RgKh;El3J8jrJXqO1bo!S~`+H!&_{=S!2m|BVRO4roDR{Tg;u%LfyuJoM#7 z9kK|{V&eGFRpUQ9x(_29NH?UG;ljO6rSb=8XnY-c4pdo7$^y{dYgFG!I()k~sj}O} zp2~n0K`p-J^nCkc6kT+Ub#TgopjSpRJ`76zNs|uRHHq3>8uljffO9Ak1*-d1?HRe% zJwD}py5Fu?xlH~B@w0J!mWX|=PPbI37>k^ekE{EW4Q`4=2P0W#ptZ;k1grg__eSba zvrb8jqMbJzH{$LQQr=R5$&un_@apK+k{Jn1b^|CBn1>5Pc4w`o8v&5B>avg z#r-@38?E(iqm>FKwnT|C=+zmZ*+gB51SLrT7DJ|r4t~tsZB(Q_V>UKizz&JDYr;*8 zS;0Niyuv(k#4~BU@ZZukH}F|_q-7iZ2^{a22sS+iB8=Y+(qaHZxmBTZkuZz+Hj({w zGJs~;e1uejH%I;-j?TiX$@hQbqZ=euI;8|9q+;eVl$Kp zdw;R^p~@t<;fmHa=dgmL?5NoHq!LH#!YA_!blxNRdnj+dv@#?e2#A;-}9`eRhxjOAfMbfh;6p5 z5Hmz;e#-TUq^jS0R06CWhw;N*#Fy+mmwkurv;OVhol*KkyjxvBX>N6hop%-YM(r)W z-L&Z!*etomFy4OrB%Jp;oH=_GB(53B%&#^WVd}^WAh4BlbYOGD3>J^brTj6XMrLp8 zcHIP_%Fyg+COq%u`$#m?{X_OZ_`mV!zGVHI3{mgn8U+ z_}&-9Z|;jQ`R0nL_!__jRTnU8yt`GLx(IZxC0&iQ)~1zW+gN>c}Pc znv8&wPd~M-ux0(DB^kkoNU^Vw(iwBIpVsEu@uE}~OD?v1DMQ{@<%U6?qPW!cDRn7c z5~+(O!JV(`r!jnr3HNsSY3z+tmy-sU3^=7KXfNas0x5jnHJk{hqBR2dr*%zx86UZ& z7BoFK{1Z7Re4ogw{BiN);sAjNK1A55J0hO>8-vGzIiuZwpmum0u3fqvxs?1ob7kAD9mKM{Du3mci|bXaX|_X&M=7<#dv5no1YgdU zKYjQQ)Us_*-e_MmmU)ts%C)tnp$iOBo&Z?9|NnYWa8rNhp&Elk#n**AHYM?4**+>B z6!3qFolWNn+9fR++8XM6RIRdUHewL}-eBy2z-go`oQ%MI(%~Yfo(_!^PWz_!?G-tR z$C;cf6!SFkQ=jB_S?Qtn&?a_a^B!p6)G}0L+p8`4EJ8Te(o*~r7TK(>jZ<9f8f1oTd*g1@=`Qt@sT0}VPNbSC+*>^yQ2v6JOG($ zw`LSZaDwu>?R%vEyww$PkFa$B`A$-zf0~q;JT7<>sG(Q8q{AGiGq^U2q-wtBZrA&m z0(qk0-j-Mxc*Yz6XzqScd5AI@6sa98f_d&5sGlvFXpQ-&J+am>jU!TkW~WjGfB^I! zFacqxm!mDYm5vP_2%D!Fj93$xwpGhjsp~WTrvW|{uwWcq6vbEmFkFIG$Wft2A`i2_=JHy7jnN z%pYslCW-Z;V2rgofF-cLl*luv2y0oc!_Uu}mx(G7kwAt=ckuKe!rfu7=3x6z+p}2! z%l*+G`a=$HhP+jd4QB_rF8$(G>5@CtmpugS)?*FLhJ+Aja^rCfK0P}_Q3jaH7(8K~ z7=`Eu8r(|lGwQn{0#n?rq8H)ZIKLCAXU-yXEfW$pkm2p(fk5cu<)S=Vy4zZ_P>*+j z{dH^1;bd;t9~b5d7{GE1dPGyin3#loCcWe}>5^ro=O`dfM<({@J)=(>R}(6mi#5Os zBudh=Fw>8y>R*>~rG3S|DfQ^^QDRrl?nPRNLTDYET0+fW8%s*60cm-+6P+d0&v6B z?ixrO7kE3}-3_nj+)&s0FxFaJd!!?7_|+AL-!RhA2|ek2E~@NUr#B|q=0K+X8}s+O zv!5^1m&>KVVCCNp*=`yK9V=>+J$M;?auS9#HGVilm?sglB~K^~3^OKm8Vm7JNns11 zUMN8#4q#MHJjsD~rc9rsY<_vX>|NnT0!R&{+U4DC{d0aMAYiA7cQjp=n0I#!plG&JI?9U` z(5AiR1LiYPoD@`AqGa_w%Tr)9S!S)z2q}03bUrm0h zE#mY+@1o6(M0DQ?D3;HEUe;G>&+)r0x3l(5L(l zv<`3|rod$#Z=i^!K|P~ql6=CUx58(S4#PfN2>vV6LYugnenfXwXN(PH-70@>HVQL@ zQtc6R=NkZI`^U6qt|km>jZ=qhsjxMv^{i<=&$Fr_;kUJ}MrvMY9U(nQ-=FsRCFxi#-l{C9D`(~# ze|fVixu*LMYxU7>+Jo~d9Tnh-CRySy8c<4NDf)z`2qB`xm-Kcxsk}I&$h$L!xaiki zYp#OUI6rWZ10GxstXB?f!B-0lN=uq~ig{!dDjB_r8%|mfTq_{0qh+adk;0(GW90^c zqYiaAFVX)i?k}5bvv!p*=DRgbLt$ou*9yA%bOu02KD~i9V1Nk(=A`W+sM6*oNjRdD0B<&b0MhySmIz5Dx+$ zxbZ(^5-LK_E}dO%1Ho7VDX9RYfkC8>C0gB{{Eo#q(4QDvPppEh{FndXo5z;^K$zVn z7bk$BFZez{MbGvVOuV%RL-q!|CFb*=1T2YbzIrfg^zTu&RXQs5x*#BHx5=x47LEVg z*ZrV;PT)OYn#XHA|Ma*=AvYpg|OU5bc)h`9DU{U*9&{ z_7lG;tq`!255)a~UHz}N;m{SB+od6G5*5k>TuNAAA*g%!Bk+Y*FnPqC&(lK$Q_Dtf zPaZUp;ftIzV$QJ0ilS1i5Qx3zMTs&G*W}{3rbL8Co}hfh7o$bgj9wgLaJk*R=h^d| zOlhK|z&ZNCgZM#;YCl-2!wjZ<@&26rJ5Rt_%fbEjouOMS))%^;SX4&Qn?3dGIdd6Q zpFBKEjOyUA+mcSjum>-#l&GUsi;E~jZ6i{@a$qlGVq(14|B){RFp8ApS65v4TRaKRcIR8`YK?Oy| z7eFTGeQl1po-w9+v1XHE2)XSo9pkq=W;_%N7HP|9HS7k8$l111tEED>RqvF;PLCV= z@xFC7nKArCRWv^nO-t@z`%!HMsPL^F5FebXKu|&s2=2d5U{2W>^nQvG#`_a9$AKf{ zRK<#2a9?8?S{>2k68d|*!+OPKc-efss8J#A*d$feS$LC^1*Ba!FV_j%LbArY=ET-A z*yA`gb*(t1C=`hWW*qpn)nDYmRLW-ylJx;;M!`KY+Z4?}V5?u9m0Y$|OIb&?Kzq

ED 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 Xl=uw=bE-P$`cO+8=aWBY%R&Fy`9ZD% literal 0 HcmV?d00001 diff --git a/third_party/zune-core/CHANGELOG.md b/third_party/zune-core/CHANGELOG.md new file mode 100644 index 0000000..bd7626a --- /dev/null +++ b/third_party/zune-core/CHANGELOG.md @@ -0,0 +1,22 @@ +## 0.2.14 + +- Fixed building with no-std +- Add `peek_at` and `pos` for writer +- Make serde non default +- Add option to make PNG add an alpha channel + +## 0.2.12 + +- Add endianness conversion +- Hide exposed values for EncoderOptions +- Add Float32 bit depth +- Remove support for BitDepth 10 and 12 +- Add bit_size method + +## 0.2.1 + +Improve documentation on various parts + +## 0.2.0 + +Initial version \ No newline at end of file diff --git a/third_party/zune-core/Cargo.toml b/third_party/zune-core/Cargo.toml new file mode 100644 index 0000000..e67655a --- /dev/null +++ b/third_party/zune-core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "zune-core" +version = "0.5.0-rc1" +edition = "2021" +description = "Core utilities for image processing in the zune family of crates" +exclude = ["tests/"] +repository = "https://github.com/etemesi254/zune-image" +keywords = ["image"] +categories = ["multimedia::images", "multimedia::encoding"] +license = "MIT OR Apache-2.0 OR Zlib" + +[features] +# When present, we can use std facilities to detect +# if a specific feature exists +# Not enabled by default. Other zune crates can enable dep:zune-core/std by default. +# But if we enable it here, they can't disable it anymore. +# See: https://github.com/rust-lang/cargo/issues/8366 +std = [] + +[dependencies] +log = { version = "0.4.17", optional = true } +serde = { version = "1.0.52", optional = true } diff --git a/third_party/zune-core/LICENSE-APACHE b/third_party/zune-core/LICENSE-APACHE new file mode 100644 index 0000000..1cd601d --- /dev/null +++ b/third_party/zune-core/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/third_party/zune-core/LICENSE-MIT b/third_party/zune-core/LICENSE-MIT new file mode 100644 index 0000000..b2cfbdc --- /dev/null +++ b/third_party/zune-core/LICENSE-MIT @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/third_party/zune-core/LICENSE-ZLIB b/third_party/zune-core/LICENSE-ZLIB new file mode 100644 index 0000000..f0648a7 --- /dev/null +++ b/third_party/zune-core/LICENSE-ZLIB @@ -0,0 +1 @@ +../../LICENSE-ZLIB \ No newline at end of file diff --git a/third_party/zune-core/README.md b/third_party/zune-core/README.md new file mode 100644 index 0000000..6627e4e --- /dev/null +++ b/third_party/zune-core/README.md @@ -0,0 +1,15 @@ +## Zune core + +Core primitives necessary for image manipulations + +This crate contains small set of primitives +necessary for image manipulations which are shared among most `zune-` family +of decoders and encoders. + +### Items present + +Currently,it contains. + +- Colorspace definitions +- Bit depth definitions. +- Decoder and encoder options \ No newline at end of file diff --git a/third_party/zune-core/src/bit_depth.rs b/third_party/zune-core/src/bit_depth.rs new file mode 100644 index 0000000..635079d --- /dev/null +++ b/third_party/zune-core/src/bit_depth.rs @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image bit depth, information and manipulations + +/// The image bit depth. +/// +/// The library successfully supports depths up to +/// 16 bits, as the underlying storage is usually a `u16`. +/// +/// This allows us to comfortably support a wide variety of images +/// e.g 10 bit av1, 16 bit png and ppm. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitDepth { + /// U8 bit depth. + /// + /// Images with such bit depth use [`u8`] to store + /// pixels and use the whole range from 0-255. + /// + /// It is currently the smallest supported bit depth + /// by the library. + /// + /// For images with bit depths lower than this, they will be scaled + /// to this bit depth + Eight, + /// U16 bit depth + /// + /// Images with such bit depths use [`u16`] to store values and use the whole range + /// i.e 0-65535 + /// + /// Data is stored and processed in native endian. + Sixteen, + /// Floating point 32 bit data, range is 0.0 to 1.0 + /// + /// Uses f32 to store data + Float32, + /// Bit depth information is unknown + Unknown +} + +/// The underlying bit representation of the image +/// +/// This represents the minimum rust type that +/// can be used to represent image data, required +/// by `Channel` struct in zune-image +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum BitType { + /// Images represented using a [`u8`] as their + /// underlying pixel storage + U8, + /// Images represented using a [`u16`] as their + /// underlying pixel storage. + U16, + /// Images represented using a [`f32`] as their + /// underlying pixel storage + F32 +} + +impl BitType { + /// Return the equivalent of the image bit type's depth + pub fn to_depth(self) -> BitDepth { + match self { + BitType::U8 => BitDepth::Eight, + BitType::U16 => BitDepth::Sixteen, + BitType::F32 => BitDepth::Float32 + } + } +} + +impl Default for BitDepth { + fn default() -> Self { + Self::Unknown + } +} + +impl BitDepth { + /// Get the max value supported by the bit depth + /// + /// During conversion from one bit depth to another + /// + /// larger values should be clamped to this bit depth + #[rustfmt::skip] + #[allow(clippy::zero_prefixed_literal)] + pub const fn max_value(self) -> u16 + { + match self + { + Self::Eight => (1 << 08) - 1, + Self::Sixteen => u16::MAX, + Self::Float32 => 1, + Self::Unknown => 0, + } + } + + /// Return the minimum number of bits that can be used to represent + /// each pixel in the image + /// + /// All bit depths below 8 return a bit type of `BitType::U8`. + /// and all those above 8 and below 16 return a bit type of `BitType::SixTeen` + /// + /// # Returns + /// An enum whose variants represent the minimum size for an unsigned integer + /// which can store the image pixels without overflow + /// + /// # Example + /// + /// ``` + /// use zune_core::bit_depth::{BitDepth, BitType}; + /// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8); + /// + /// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16); + /// ``` + /// + /// See also [size_of](BitDepth::size_of) + pub const fn bit_type(self) -> BitType { + match self { + Self::Eight => BitType::U8, + Self::Sixteen => BitType::U16, + Self::Float32 => BitType::F32, + Self::Unknown => panic!("Unknown bit type") + } + } + /// Get the number of bytes needed to store a specific bit depth + /// + /// + /// # Example + /// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store + /// the pixels, and a size_of [`u8`] is 1 + /// + /// For images greater than 8 bits and less than 16 bits(2 bytes), we can use a [`u16`] to + /// store the pixels, a size_of [`u16`] is 2. + /// ``` + /// use zune_core::bit_depth::BitDepth; + /// let depth = BitDepth::Sixteen; + /// // greater 12 bits is greater than 8 and less than 16 + /// assert_eq!(depth.size_of(),2); + /// ``` + pub const fn size_of(self) -> usize { + match self { + Self::Eight => core::mem::size_of::(), + Self::Sixteen => core::mem::size_of::(), + Self::Float32 => core::mem::size_of::(), + Self::Unknown => panic!("Unknown bit type") + } + } + pub const fn bit_size(&self) -> usize { + self.size_of() * 8 + } +} + +/// Byte endianness of returned samples +/// this is useful when the decoder returns samples which span more +/// than one byte yet the type returned is `&[u8]` +/// +/// This helps you interpret how those bytes should be reconstructed +/// to a higher order type +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum ByteEndian { + /// Little Endian byte-order + LE, + /// Big Endian byte-order + BE +} diff --git a/third_party/zune-core/src/bytestream.rs b/third_party/zune-core/src/bytestream.rs new file mode 100644 index 0000000..e726314 --- /dev/null +++ b/third_party/zune-core/src/bytestream.rs @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! A simple implementation of a bytestream reader +//! and writer. +//! +//! This module contains two main structs that help in +//! byte reading and byte writing +//! +//! Useful for a lot of image readers and writers, it's put +//! here to minimize code reuse +pub use reader::ZReader; +pub use traits::*; +pub use writer::ZWriter; + +pub use crate::bytestream::reader::no_std_readers::*; +//use crate::bytestream::reader::std_readers::*; +pub use crate::bytestream::reader::ZByteIoError; + +mod reader; +mod traits; +mod writer; diff --git a/third_party/zune-core/src/bytestream/reader.rs b/third_party/zune-core/src/bytestream/reader.rs new file mode 100644 index 0000000..a91aaad --- /dev/null +++ b/third_party/zune-core/src/bytestream/reader.rs @@ -0,0 +1,458 @@ +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; +use core::fmt::Formatter; + +pub(crate) mod no_std_readers; +pub(crate) mod std_readers; +use crate::bytestream::ZByteReaderTrait; + +/// Enumeration of possible methods to seek within an I/O object. +/// +/// It is analogous to the [SeekFrom](std::io::SeekFrom) in the std library but +/// it's here to allow this to work in no-std crates +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +pub enum ZSeekFrom { + /// Sets the offset to the provided number of bytes. + Start(u64), + + /// Sets the offset to the size of this object plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + End(i64), + + /// Sets the offset to the current position plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + Current(i64) +} + +impl ZSeekFrom { + /// Convert to [SeekFrom](std::io::SeekFrom) from the `std::io` library + /// + /// This is only present when std feature is present + #[cfg(feature = "std")] + pub(crate) fn to_std_seek(self) -> std::io::SeekFrom { + match self { + ZSeekFrom::Start(pos) => std::io::SeekFrom::Start(pos), + ZSeekFrom::End(pos) => std::io::SeekFrom::End(pos), + ZSeekFrom::Current(pos) => std::io::SeekFrom::Current(pos) + } + } +} + +pub enum ZByteIoError { + /// A standard library error + /// Only available with the `std` feature + #[cfg(feature = "std")] + StdIoError(std::io::Error), + /// An error converting from one type to another + TryFromIntError(core::num::TryFromIntError), + /// Not enough bytes to satisfy a read + // requested, read + NotEnoughBytes(usize, usize), + /// The output buffer is too small to write the bytes + NotEnoughBuffer(usize, usize), + /// An error that may occur randomly + Generic(&'static str), + /// An error that occurred during a seek operation + SeekError(&'static str), + /// An error that occurred during a seek operation + SeekErrorOwned(String) +} + +impl core::fmt::Debug for ZByteIoError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + #[cfg(feature = "std")] + ZByteIoError::StdIoError(err) => { + writeln!(f, "Underlying I/O error {}", err) + } + ZByteIoError::TryFromIntError(err) => { + writeln!(f, "Cannot convert to int {}", err) + } + ZByteIoError::NotEnoughBytes(expected, found) => { + writeln!(f, "Not enough bytes, expected {expected} but found {found}") + } + ZByteIoError::NotEnoughBuffer(expected, found) => { + writeln!( + f, + "Not enough buffer to write {expected} bytes, buffer size is {found}" + ) + } + ZByteIoError::Generic(err) => { + writeln!(f, "Generic I/O error: {err}") + } + ZByteIoError::SeekError(err) => { + writeln!(f, "Seek error: {err}") + } + ZByteIoError::SeekErrorOwned(err) => { + writeln!(f, "Seek error {err}") + } + } + } +} + +#[cfg(feature = "std")] +impl From for ZByteIoError { + fn from(value: std::io::Error) -> Self { + ZByteIoError::StdIoError(value) + } +} + +impl From for ZByteIoError { + fn from(value: core::num::TryFromIntError) -> Self { + ZByteIoError::TryFromIntError(value) + } +} + +impl From<&'static str> for ZByteIoError { + fn from(value: &'static str) -> Self { + ZByteIoError::Generic(value) + } +} + +/// The image reader wrapper +/// +/// This wraps anything that implements [ZByteReaderTrait] and +/// extends the ability of the core trait methods by providing +/// utilities like endian aware byte functions. +/// +/// This prevents each implementation from providing its own +pub struct ZReader { + inner: T, + temp_buffer: Vec +} + +impl ZReader { + /// Create a new reader from a source + /// that implements the [ZByteReaderTrait] + pub fn new(source: T) -> ZReader { + ZReader { + inner: source, + temp_buffer: vec![] + } + } + /// Destroy this reader returning + /// the underlying source of the bytes + /// from which we were decoding + #[inline(always)] + pub fn consume(self) -> T { + self.inner + } + /// Skip ahead ignoring `num` bytes + /// + /// For more advanced seek methods see [Self::seek] that allows + /// moving around via more advanced ways + /// + /// # Arguments + /// - num: The number of bytes to skip. + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - `Error` If something went wrong + #[inline(always)] + pub fn skip(&mut self, num: usize) -> Result { + self.inner.z_seek(ZSeekFrom::Current(num as i64)) + } + /// Move back from current position to a previous + /// position + /// + /// For more advanced seek methods see [Self::seek] that allows + /// moving around via more advanced ways + /// + /// # Arguments + /// - `num`: Positions to move before the current cursor + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - `Error` If something went wrong + #[inline(always)] + pub fn rewind(&mut self, num: usize) -> Result { + self.inner.z_seek(ZSeekFrom::Current(-(num as i64))) + } + /// Move around a stream of bytes + /// + /// This is analogous to the [std::io::Seek] trait with the same ergonomics + /// only implemented to allow use in a `no_std` environment + /// + /// # Arguments + /// - `from`: The seek operation type. + /// + /// # Returns + /// - `Ok(u64)`: The new position from the start of the stream. + /// - Error if something went wrong. + #[inline(always)] + pub fn seek(&mut self, from: ZSeekFrom) -> Result { + self.inner.z_seek(from) + } + + /// Read a single byte from the underlying stream + /// + /// If an error occurs, it will return `0` as default output + /// hence it may be difficult to distinguish a `0` from the underlying source + /// and a `0` from an error. + /// For that there is [Self::read_u8_err] + /// + /// # Returns. + /// - The next byte on the stream. + /// + #[inline(always)] + pub fn read_u8(&mut self) -> u8 { + self.inner.read_byte_no_error() + } + + /// Read a single byte returning an error if the read cannot be satisfied + /// + /// # Returns + /// - `Ok(u8)`: The next byte + /// - Error if the byte read could not be satisfied + #[inline(always)] + pub fn read_u8_err(&mut self) -> Result { + let mut buf = [0]; + self.inner.read_const_bytes(&mut buf)?; + Ok(buf[0]) + } + + /// Look ahead position bytes and return a reference + /// to num_bytes from that position, or an error if the + /// peek would be out of bounds. + /// + /// This doesn't increment the position, bytes would have to be discarded + /// at a later point. + #[inline] + pub fn peek_at(&mut self, position: usize, num_bytes: usize) -> Result<&[u8], ZByteIoError> { + // short circuit for zero + // important since implementations like File will + // cause a syscall on skip + if position != 0 { + // skip position bytes from start + self.skip(position)?; + } + // resize buffer + self.temp_buffer.resize(num_bytes, 0); + // read bytes + match self.inner.peek_exact_bytes(&mut self.temp_buffer[..]) { + Ok(_) => { + // rewind back to where we were + if position != 0 { + self.rewind(position)?; + } + Ok(&self.temp_buffer) + } + Err(e) => Err(e) + } + } + /// Read a fixed number of known bytes to a buffer and return the bytes or an error + /// if it occurred. + /// + /// The size of the `N` value must be small enough to fit the stack space otherwise + /// this will cause a stack overflow :) + /// + /// If you can ignore errors, you can use [Self::read_fixed_bytes_or_zero] + /// + /// # Returns + /// - `Ok([u8;N])`: The bytes read from the source + /// - An error if it occurred. + #[inline(always)] + pub fn read_fixed_bytes_or_error(&mut self) -> Result<[u8; N], ZByteIoError> { + let mut byte_store: [u8; N] = [0; N]; + match self.inner.read_const_bytes(&mut byte_store) { + Ok(_) => Ok(byte_store), + Err(e) => Err(e) + } + } + /// Read a fixed bytes to an array and if that is impossible, return an array containing + /// zeros + /// + /// If you want to handle errors, use [Self::read_fixed_bytes_or_error] + #[inline(always)] + pub fn read_fixed_bytes_or_zero(&mut self) -> [u8; N] { + let mut byte_store: [u8; N] = [0; N]; + self.inner.read_const_bytes_no_error(&mut byte_store); + byte_store + } + + /// Move the cursor to a fixed position in the stream + /// + /// This will move the cursor to exacltly `position` bytes from the start of the buffer + /// + /// # Arguments + /// - `position`: The current position to move the cursor. + #[inline] + pub fn set_position(&mut self, position: usize) -> Result<(), ZByteIoError> { + self.seek(ZSeekFrom::Start(position as u64))?; + + Ok(()) + } + + /// Return true if the underlying buffer can no longer produce bytes + /// + /// This call may be expensive depending on the underlying buffer type, e.g if + /// it's a file, we have to ask the os whether we have more contents, or in other words make a syscall. + /// + /// Use that wisely + /// + /// # Returns + /// - `Ok(bool)`: True if we are in `EOF`, false if we can produce more bytes + /// - Error if something went wrong + #[inline(always)] + pub fn eof(&mut self) -> Result { + self.inner.is_eof() + } + + /// Return the current position of the inner reader or an error + /// if that occurred when reading. + /// + /// Like [eof](Self::eof), the perf characteristics may vary depending on underlying reader + /// + /// # Returns + /// - `Ok(u64)`: The current position of the inner reader + #[inline(always)] + pub fn position(&mut self) -> Result { + self.inner.z_position() + } + + /// Read a fixed number of bytes from the underlying reader returning + /// an error if that can't be satisfied + /// + /// Similar to [std::io::Read::read_exact] + /// + /// # Returns + /// - `Ok(())`: If the read was successful + /// - An error if the read was unsuccessful including failure to fill the whole bytes + pub fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + self.inner.read_exact_bytes(buf) + } + + /// Read some bytes from the inner reader, and return number of bytes read + /// + /// The implementation may not read bytes enough to fill the buffer + /// + /// Similar to [std::io::Read::read] + /// + /// # Returns + /// - `Ok(usize)`: Number of bytes actually read to the buffer + /// - An error if something went wrong + pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + self.inner.read_bytes(buf) + } +} + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} +macro_rules! get_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl ZReader + { + #[inline(always)] + fn $name(&mut self, mode: Mode) -> $int_type + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + self.inner.read_const_bytes_no_error(&mut space); + + match mode { + Mode::BE => $int_type::from_be_bytes(space), + Mode::LE => $int_type::from_le_bytes(space) + } + } + + #[inline(always)] + fn $name2(&mut self, mode: Mode) -> Result<$int_type, ZByteIoError> + { + const SIZE_OF_VAL: usize = core::mem::size_of::<$int_type>(); + + let mut space = [0; SIZE_OF_VAL]; + + match self.inner.read_const_bytes(&mut space) + { + Ok(_) => match mode { + Mode::BE => Ok($int_type::from_be_bytes(space)), + Mode::LE => Ok($int_type::from_le_bytes(space)) + }, + Err(e) => Err(e) + } + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name3(&mut self) -> Result<$int_type, ZByteIoError> + { + self.$name2(Mode::BE) + } + + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," read.")] + #[inline] + pub fn $name4(&mut self) -> Result<$int_type, ZByteIoError> + { + self.$name2(Mode::LE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name5(&mut self) -> $int_type + { + self.$name(Mode::BE) + } + #[doc=concat!("Read ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning 0 if the underlying buffer does not have enough bytes for a ",stringify!($int_type)," read.")] + #[inline(always)] + pub fn $name6(&mut self) -> $int_type + { + self.$name(Mode::LE) + } + } + }; +} + +get_single_type!( + get_u16_inner_or_default, + get_u16_inner_or_die, + get_u16_be_err, + get_u16_le_err, + get_u16_be, + get_u16_le, + u16 +); +get_single_type!( + get_u32_inner_or_default, + get_u32_inner_or_die, + get_u32_be_err, + get_u32_le_err, + get_u32_be, + get_u32_le, + u32 +); +get_single_type!( + get_u64_inner_or_default, + get_u64_inner_or_die, + get_u64_be_err, + get_u64_le_err, + get_u64_be, + get_u64_le, + u64 +); + +#[cfg(feature = "std")] +impl std::io::Read for ZReader +where + T: ZByteReaderTrait +{ + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + use std::io::ErrorKind; + self.read_bytes(buf) + .map_err(|e| std::io::Error::new(ErrorKind::Other, format!("{:?}", e))) + } +} diff --git a/third_party/zune-core/src/bytestream/reader/no_std_readers.rs b/third_party/zune-core/src/bytestream/reader/no_std_readers.rs new file mode 100644 index 0000000..0334121 --- /dev/null +++ b/third_party/zune-core/src/bytestream/reader/no_std_readers.rs @@ -0,0 +1,198 @@ +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; +use crate::bytestream::ZByteReaderTrait; +/// Wraps an in memory buffer providing it with a `Seek` method +/// but works in `no_std` environments +/// +/// `std::io::Cursor` is available in std environments, but we also need support +/// for `no_std` environments so this serves as a drop in replacement +pub struct ZCursor> { + stream: T, + position: usize +} + +impl> ZCursor { + pub fn new(buffer: T) -> ZCursor { + ZCursor { + stream: buffer, + position: 0 + } + } +} + +impl> ZCursor { + /// Move forward `num` bytes from + /// the current position. + /// + /// It doesn't check that position overflowed, new position + /// may point past the internal buffer, all subsequent reads will + /// either return an error or zero depending on the method called + #[inline] + pub fn skip(&mut self, num: usize) { + // Can this overflow ?? + self.position = self.position.wrapping_add(num); + } + /// Move back `num` bytes from the current position + /// + /// + /// This saturates at zero, it can never be negative or wraparound + /// when the value becomes too small + #[inline] + pub fn rewind(&mut self, num: usize) { + self.position = self.position.saturating_sub(num); + } +} + +impl> ZByteReaderTrait for ZCursor { + #[inline(always)] + fn read_byte_no_error(&mut self) -> u8 { + let byte = self.stream.as_ref().get(self.position).unwrap_or(&0); + self.position += 1; + *byte + } + #[inline(always)] + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + let bytes_read = self.read_bytes(buf)?; + if bytes_read != buf.len() { + // restore read to initial position it was in. + self.rewind(bytes_read); + // not all bytes were read. + return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len())); + } + Ok(()) + } + + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> { + if self.position + N <= self.stream.as_ref().len() { + // we are in bounds + let reference = self.stream.as_ref(); + let position = self.position; + if let Some(buf_ref) = reference.get(position..position + N) { + self.position += N; + buf.copy_from_slice(buf_ref); + return Ok(()); + } + } + Err(ZByteIoError::Generic("Cannot satisfy read")) + } + + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]) { + if self.position + N <= self.stream.as_ref().len() { + // we are in bounds + let reference = self.stream.as_ref(); + let position = self.position; + if let Some(buf_ref) = reference.get(position..position + N) { + self.position += N; + buf.copy_from_slice(buf_ref); + } + } + } + + #[inline(always)] + fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + let len = self.peek_bytes(buf)?; + self.skip(len); + Ok(len) + } + + #[inline(always)] + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result { + let stream_end = self.stream.as_ref().len(); + + let start = core::cmp::min(self.position, stream_end); + let end = core::cmp::min(self.position + buf.len(), stream_end); + + let slice = self.stream.as_ref().get(start..end).unwrap(); + buf[..slice.len()].copy_from_slice(slice); + let len = slice.len(); + + Ok(len) + } + + #[inline(always)] + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + self.read_exact_bytes(buf)?; + self.rewind(buf.len()); + Ok(()) + } + + #[inline(always)] + fn z_seek(&mut self, from: ZSeekFrom) -> Result { + let (base_pos, offset) = match from { + ZSeekFrom::Start(n) => { + self.position = n as usize; + return Ok(n); + } + ZSeekFrom::End(n) => (self.stream.as_ref().len(), n as isize), + ZSeekFrom::Current(n) => (self.position, n as isize) + }; + match base_pos.checked_add_signed(offset) { + Some(n) => { + self.position = n; + Ok(self.position as u64) + } + None => Err(ZByteIoError::SeekError("Negative seek")) + } + } + + #[inline(always)] + fn is_eof(&mut self) -> Result { + Ok(self.position >= self.stream.as_ref().len()) + } + #[inline(always)] + fn z_position(&mut self) -> Result { + Ok(self.position as u64) + } + + fn read_remaining(&mut self, sink: &mut alloc::vec::Vec) -> Result { + let start = self.position; + let end = self.stream.as_ref().len(); + match self.stream.as_ref().get(start..end) { + None => { + return Err(ZByteIoError::Generic( + "Somehow read remaining couldn't satisfy it's invariants" + )) + } + Some(e) => { + sink.extend_from_slice(e); + } + } + self.skip(end - start); + Ok(end - start) + } +} + +#[cfg(feature = "std")] +impl> std::io::Seek for ZCursor { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + let (base_pos, offset) = match pos { + std::io::SeekFrom::Start(n) => { + self.position = n as usize; + return Ok(n); + } + std::io::SeekFrom::End(n) => (self.stream.as_ref().len(), n as isize), + std::io::SeekFrom::Current(n) => (self.position, n as isize) + }; + match base_pos.checked_add_signed(offset) { + Some(n) => { + self.position = n; + Ok(self.position as u64) + } + None => Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Negative seek" + )) + } + } +} +// +// #[cfg(feature = "std")] +// impl> std::io::Read for ZCursor { +// fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +// self.read_bytes(buf).map_err(|x|{ std::io::Error::new()}) +// } +// } +impl> From for ZCursor { + fn from(value: T) -> Self { + ZCursor::new(value) + } +} diff --git a/third_party/zune-core/src/bytestream/reader/std_readers.rs b/third_party/zune-core/src/bytestream/reader/std_readers.rs new file mode 100644 index 0000000..014d0bd --- /dev/null +++ b/third_party/zune-core/src/bytestream/reader/std_readers.rs @@ -0,0 +1,100 @@ +#![cfg(feature = "std")] + +use std::io; +use std::io::SeekFrom; + +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; +use crate::bytestream::ZByteReaderTrait; +// note (cae): If Rust ever stabilizes trait specialization, specialize this for Cursor +impl ZByteReaderTrait for T { + #[inline(always)] + fn read_byte_no_error(&mut self) -> u8 { + let mut buf = [0]; + let _ = self.read(&mut buf); + buf[0] + } + #[inline(always)] + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + let mut bytes_read = 0; + + while bytes_read < buf.len() { + match self.read(&mut buf[bytes_read..]) { + Ok(0) => { + // if a read returns zero bytes read, it means it encountered an EOF so we seek + // back to where we started because some paths may aggressively read forward and + // ZCursor maintains the position. + + // NB: (cae) [tag=perf] This adds a branch on every read, and will slow down every function + // resting on it. Sorry + self.seek(SeekFrom::Current(-(bytes_read as i64))) + .map_err(ZByteIoError::from)?; + return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len())); + } + Ok(bytes) => { + bytes_read += bytes; + } + Err(e) => return Err(ZByteIoError::from(e)) + } + } + + Ok(()) + } + + #[inline] + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> { + self.read_exact_bytes(buf) + } + + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]) { + let _ = self.read_const_bytes(buf); + } + + #[inline(always)] + fn read_bytes(&mut self, buf: &mut [u8]) -> Result { + self.read(buf).map_err(ZByteIoError::from) + } + + #[inline(always)] + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result { + // first read bytes to the buffer + let bytes_read = self.read_bytes(buf)?; + let converted = -i64::try_from(bytes_read).map_err(ZByteIoError::from)?; + self.seek(std::io::SeekFrom::Current(converted)) + .map_err(ZByteIoError::from)?; + + Ok(bytes_read) + } + + #[inline(always)] + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> { + // first read bytes to the buffer + self.read_exact_bytes(buf)?; + let converted = -i64::try_from(buf.len()).map_err(ZByteIoError::from)?; + self.seek(std::io::SeekFrom::Current(converted)) + .map_err(ZByteIoError::from)?; + + Ok(()) + } + + #[inline(always)] + fn z_seek(&mut self, from: ZSeekFrom) -> Result { + self.seek(from.to_std_seek()).map_err(ZByteIoError::from) + } + + #[inline(always)] + fn is_eof(&mut self) -> Result { + self.fill_buf() + .map(|b| b.is_empty()) + .map_err(ZByteIoError::from) + } + + #[inline(always)] + fn z_position(&mut self) -> Result { + self.stream_position().map_err(ZByteIoError::from) + } + + #[inline(always)] + fn read_remaining(&mut self, sink: &mut Vec) -> Result { + self.read_to_end(sink).map_err(ZByteIoError::from) + } +} diff --git a/third_party/zune-core/src/bytestream/traits.rs b/third_party/zune-core/src/bytestream/traits.rs new file mode 100644 index 0000000..e9f3af7 --- /dev/null +++ b/third_party/zune-core/src/bytestream/traits.rs @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ +//! Traits for reading and writing images in zune +//! +//! +//! This exposes the traits and implementations for readers +//! and writers in the zune family of decoders and encoders. + +use crate::bytestream::reader::{ZByteIoError, ZSeekFrom}; + +/// The de-facto Input trait implemented for readers. +/// +/// This provides the basic functions needed to quick and sometimes +/// heap free I/O for the zune image decoders with easy support for extending it +/// to multiple implementations. +/// +/// # Considerations +/// +/// If you have an in memory buffer, prefer [`ZCursor`](crate::bytestream::ZCursor) over [`Cursor`](std::io::Cursor). +/// We implement this trait for two types, `ZCursor`, and any thing that implements `BufRead`+`Seek`, `Cursor` falls in the latter +/// and since Rust doesn't have specialization for traits, we can only implement it once. This means functions like +/// [`read_byte_no_error`](crate::bytestream::ZByteReaderTrait::read_byte_no_error) are slower than they should be for `Cursor`. +/// +pub trait ZByteReaderTrait { + /// Read a single byte from the decoder and return + /// `0` if we can't read the byte, e.g because of EOF + /// + /// The implementation should try to be as fast as possible as this is called + /// from some hot loops where it may become the bottleneck + fn read_byte_no_error(&mut self) -> u8; + /// Read exact bytes required to fill `buf` or return an error if that isn't possible + /// + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>; + + /// Read exact bytes required to fill `buf` or return an error if that isn't possible + /// + /// This is the same as [`read_exact_bytes`](Self::read_exact_bytes) but implemented as a separate + /// method to allow some implementations to optimize it to cost fewer instructions + /// + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_const_bytes(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError>; + + /// Read exact bytes required to fill `buf` or ignore buf entirely if you can't fill it + /// due to an error like the inability to fill the buffer completely + /// ## Arguments + /// - `buf`: Buffer to fill with bytes from the underlying reader + /// ## Errors + /// In case of an error, the implementation should not increment the internal position + fn read_const_bytes_no_error(&mut self, buf: &mut [u8; N]); + + /// Read bytes into `buf` returning how many bytes you have read or an error if one occurred + /// + /// This doesn't guarantee that buf will be filled with bytes for such a guarantee see + /// [`read_exact_bytes`](Self::read_exact_bytes) + /// + /// ## Arguments + /// - `buf`: The buffer to fill with bytes + /// + /// ## Returns + /// - `Ok(usize)` - Actual bytes read into the buffer + /// - `Err()` - The error encountered when reading bytes for which we couldn't recover + fn read_bytes(&mut self, buf: &mut [u8]) -> Result; + /// Reads data into provided buffer but does not advance read position. + /// + /// + fn peek_bytes(&mut self, buf: &mut [u8]) -> Result; + fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>; + /// Seek into a new position from the buffer + /// + /// This is similar to the [seek](std::io::Seek::seek) function in the [Seek](std::io::Seek) trait + /// but implemented to work for no-std environments + fn z_seek(&mut self, from: ZSeekFrom) -> Result; + /// Report whether we are at the end of a stream. + /// + /// ## Warning + /// This may cause an additional syscall e.g when we are reading from a file, we must query the file + /// multiple times to check if we really are at the end of the file and the user didn't sneakily + /// add more contents to it hence use it with care + /// + /// ## Returns + /// - `Ok(bool)` - The answer to whether or not we are at end of file + /// - `Err()` - The error that occurred when we queried the underlying reader if we were at EOF + fn is_eof(&mut self) -> Result; + + /// Return the current position of the inner cursor. + /// + /// This can be used to check the advancement of the cursor + fn z_position(&mut self) -> Result; + /// Read all bytes remaining in this input to `sink` until we hit eof + /// + /// # Returns + /// - `Ok(usize)` The actual number of bytes added to the sink + /// - `Err()` An error that occurred when reading bytes + fn read_remaining(&mut self, sink: &mut alloc::vec::Vec) -> Result; +} + +/// The writer trait implemented for zune-image library of encoders +/// +/// Anything that implements this trait can be used as a sink +/// for writing encoded images +pub trait ZByteWriterTrait { + /// Write some bytes into the sink returning number of bytes written or + /// an error if something bad happened + /// + /// An implementation is free to write less bytes that are in buf, so the bytes written + /// cannot be guaranteed to be fully written + fn write_bytes(&mut self, buf: &[u8]) -> Result; + /// Write all bytes to the buffer or return an error if something occurred + /// + /// This will always write all bytes, if it can't fully write all bytes, it will + /// error out + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError>; + /// Write a fixed number of bytes and error out if we can't write the bytes + /// + /// This is provided to allow for optimized writes where possible. (when the compiler can const fold them) + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError>; + /// Ensure bytes are written to the sink. + /// + /// Implementations should treat this like linux `fsync`, and should implement + /// whatever writer's implementation of fsync should look like + /// + /// After this, the encoder should be able to guarantee that all in-core data is synced with the + /// storage decive + fn flush_bytes(&mut self) -> Result<(), ZByteIoError>; + + /// A hint to tell the implementation how big of a size we expect the image to be + /// An implementation like in memory `Vec` can use this to reserve additional memory to + /// prevent reallocation when encoding + /// + /// This is just a hint, akin to calling `Vec::reserve` and should be treated as such. + /// If your implementation doesn't support such, e.g file or mutable slices, it's okay to return + /// `Ok(())` + fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError>; +} diff --git a/third_party/zune-core/src/bytestream/writer.rs b/third_party/zune-core/src/bytestream/writer.rs new file mode 100644 index 0000000..8b1fc63 --- /dev/null +++ b/third_party/zune-core/src/bytestream/writer.rs @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ +use crate::bytestream::{ZByteIoError, ZByteWriterTrait}; + +mod no_std_writer; +mod std_writer; + +enum Mode { + // Big endian + BE, + // Little Endian + LE +} + +/// Encapsulates a simple Byte writer with +/// support for Endian aware writes +pub struct ZWriter { + buffer: T, + bytes_written: usize +} + +impl ZWriter { + /// Write bytes from the buf into the bytestream + /// and return how many bytes were written + /// + /// # Arguments + /// - `buf`: The bytes to be written to the bytestream + /// + /// # Returns + /// - `Ok(usize)` - Number of bytes written + /// This number may be less than `buf.len()` if the length of the buffer is greater + /// than the internal bytestream length + /// + /// If you want to be sure that all bytes were written, see [`write_all`](Self::write_all) + /// + #[inline] + pub fn write(&mut self, buf: &[u8]) -> Result { + let bytes_written = self.buffer.write_bytes(buf)?; + self.bytes_written += bytes_written; + Ok(bytes_written) + } + /// Write all bytes from `buf` into the bytestream and return + /// and panic if not all bytes were written to the bytestream + /// + /// # Arguments + /// - `buf`: The bytes to be written into the bytestream + /// + ///# Returns + /// - `Ok(())`: Indicates all bytes were written into the bytestream + /// - `Err(&static str)`: In case all the bytes could not be written + /// to the stream + pub fn write_all(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.buffer.write_all_bytes(buf)?; + self.bytes_written += buf.len(); + Ok(()) + } + /// Create a new bytestream writer + /// Bytes are written from the start to the end and not assumptions + /// are made of the nature of the underlying stream + /// + /// # Arguments + pub fn new(data: T) -> ZWriter { + ZWriter { + buffer: data, + bytes_written: 0 + } + } + + /// Write a single byte into the bytestream or error out + /// if there is not enough space + /// + /// # Example + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let mut buf = [0;10]; + /// let mut stream = ZWriter::new(&mut buf[..]); + /// assert!(stream.write_u8_err(34).is_ok()); + /// ``` + /// No space + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let mut no_space = []; + /// let mut stream = ZWriter::new(&mut no_space[..]); + /// assert!(stream.write_u8_err(32).is_err()); + /// ``` + /// + #[inline] + pub fn write_u8_err(&mut self, byte: u8) -> Result<(), ZByteIoError> { + self.write_const_bytes(&[byte]) + } + /// Write a fixed compile time known number of bytes to the sink + /// + /// This is provided since some implementations can optimize such writes by eliminating + /// some redundant code. + #[inline] + pub fn write_const_bytes( + &mut self, byte: &[u8; N] + ) -> Result<(), ZByteIoError> { + self.buffer.write_const_bytes(byte)?; + self.bytes_written += N; + Ok(()) + } + + /// Write a single byte in the stream or don't write + /// anything if the buffer is full and cannot support the byte read + /// + #[inline] + pub fn write_u8(&mut self, byte: u8) { + let _ = self.write_const_bytes(&[byte]); + } + /// Return the number of bytes written by this encoder + /// + /// The encoder keeps information of how many bytes were written and this method + /// returns that value. + /// + /// # Returns + /// Number of bytes written + pub fn bytes_written(&self) -> usize { + self.bytes_written + } + + /// Reserve some additional space to write. + /// + /// Some sinks like `Vec` allow reallocation and to prevent too much reallocation + /// one can use this to reserve additional space to encode + /// + /// # Example + /// + /// ``` + /// use zune_core::bytestream::ZWriter; + /// let space_needed = 10; // Assume the image will fit into 10 bytes + /// let mut output = Vec::new(); + /// let mut sink = ZWriter::new(&mut output); + /// // now reserve some space + ///sink.reserve(space_needed).unwrap(); + /// // at this point, we can assume that ZWriter allocated space for output + /// ``` + pub fn reserve(&mut self, additional: usize) -> Result<(), ZByteIoError> { + self.buffer.reserve_capacity(additional) + } + /// Consume the writer and return the inner sink + /// we were writing to. + /// + /// After this, the writer can no longer be used + pub fn inner(self) -> T { + self.buffer + } + /// Return an immutable reference to the inner sink + pub fn inner_ref(&self) -> &T { + &self.buffer + } + /// Return a mutable reference to the inner sink + pub fn inner_mut(&mut self) -> &mut T { + &mut self.buffer + } +} + +macro_rules! write_single_type { + ($name:tt,$name2:tt,$name3:tt,$name4:tt,$name5:tt,$name6:tt,$int_type:tt) => { + impl ZWriter + { + #[inline(always)] + fn $name(&mut self, byte: $int_type, mode: Mode) -> Result<(), ZByteIoError> + { + + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + self.write_const_bytes(&bytes) + } + #[inline(always)] + fn $name2(&mut self, byte: $int_type, mode: Mode) + { + + // get bits, depending on mode. + // This should be inlined and not visible in + // the generated binary since mode is a compile + // time constant. + let bytes = match mode + { + Mode::BE => byte.to_be_bytes(), + Mode::LE => byte.to_le_bytes() + }; + let _ = self.write_const_bytes(&bytes); + + + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name3(&mut self, byte: $int_type) -> Result<(), ZByteIoError> + { + self.$name(byte, Mode::BE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Returning an error if the underlying buffer cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name4(&mut self, byte: $int_type) -> Result<(), ZByteIoError> + { + self.$name(byte, Mode::LE) + } + + #[doc=concat!("Write ",stringify!($int_type)," as a big endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name5(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::BE) + } + #[doc=concat!("Write ",stringify!($int_type)," as a little endian integer")] + #[doc=concat!("Or don't write anything if the reader cannot support a ",stringify!($int_type)," write.")] + #[inline] + pub fn $name6(&mut self, byte: $int_type) + { + self.$name2(byte, Mode::LE) + } + } + }; +} + +write_single_type!( + write_u64_inner_or_die, + write_u64_inner_or_none, + write_u64_be_err, + write_u64_le_err, + write_u64_be, + write_u64_le, + u64 +); + +write_single_type!( + write_u32_inner_or_die, + write_u32_inner_or_none, + write_u32_be_err, + write_u32_le_err, + write_u32_be, + write_u32_le, + u32 +); + +write_single_type!( + write_u16_inner_or_die, + write_u16_inner_or_none, + write_u16_be_err, + write_u16_le_err, + write_u16_be, + write_u16_le, + u16 +); diff --git a/third_party/zune-core/src/bytestream/writer/no_std_writer.rs b/third_party/zune-core/src/bytestream/writer/no_std_writer.rs new file mode 100644 index 0000000..fd5fca8 --- /dev/null +++ b/third_party/zune-core/src/bytestream/writer/no_std_writer.rs @@ -0,0 +1,70 @@ +// We cannot use the below impls and std ones because we'll re-implement the +// same trait fot &[u8] which is blanketed by write. Ending up with two separate implementations +#![cfg(not(feature = "std"))] +use crate::bytestream::{ZByteIoError, ZByteWriterTrait}; + +impl ZByteWriterTrait for &mut [u8] { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + // got from the write of std + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + Ok(amt) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + if buf.len() > self.len() { + return Err(ZByteIoError::NotEnoughBuffer(self.len(), buf.len())); + } + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + + Ok(()) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + if N > self.len() { + return Err(ZByteIoError::NotEnoughBuffer(self.len(), N)); + } + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(&buf[..amt]); + *self = b; + Ok(()) + } + + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + Ok(()) + } + fn reserve_capacity(&mut self, _: usize) -> Result<(), ZByteIoError> { + // can't really pre-allocate anything here + Ok(()) + } +} + +impl ZByteWriterTrait for &mut alloc::vec::Vec { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.extend_from_slice(buf); + Ok(()) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + self.extend_from_slice(buf); + Ok(()) + } + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + Ok(()) + } + fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError> { + self.reserve(size); + Ok(()) + } +} diff --git a/third_party/zune-core/src/bytestream/writer/std_writer.rs b/third_party/zune-core/src/bytestream/writer/std_writer.rs new file mode 100644 index 0000000..d82aba5 --- /dev/null +++ b/third_party/zune-core/src/bytestream/writer/std_writer.rs @@ -0,0 +1,27 @@ +#![cfg(feature = "std")] + +use std::io::Write; + +use crate::bytestream::ZByteIoError; + +impl crate::bytestream::ZByteWriterTrait for T { + fn write_bytes(&mut self, buf: &[u8]) -> Result { + self.write(buf).map_err(ZByteIoError::StdIoError) + } + + fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError> { + self.write_all(buf).map_err(ZByteIoError::StdIoError) + } + + fn write_const_bytes(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError> { + self.write_all_bytes(buf) + } + fn flush_bytes(&mut self) -> Result<(), ZByteIoError> { + self.flush().map_err(ZByteIoError::StdIoError) + } + fn reserve_capacity(&mut self, _: usize) -> Result<(), ZByteIoError> { + // we can't reserve capacity, sorry to implementations where this + // matters + Ok(()) + } +} diff --git a/third_party/zune-core/src/colorspace.rs b/third_party/zune-core/src/colorspace.rs new file mode 100644 index 0000000..8bdc916 --- /dev/null +++ b/third_party/zune-core/src/colorspace.rs @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Image Colorspace information and manipulation utilities. + +/// All possible image colorspaces +/// Some of them aren't yet supported exist here. +#[allow(clippy::upper_case_acronyms)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum ColorSpace { + /// Red, Green , Blue + RGB, + /// Red, Green, Blue, Alpha + RGBA, + /// YUV colorspace + YCbCr, + /// Grayscale colorspace + Luma, + /// Grayscale with alpha colorspace + LumaA, + YCCK, + /// Cyan , Magenta, Yellow, Black + CMYK, + /// Blue, Green, Red + BGR, + /// Blue, Green, Red, Alpha + BGRA, + /// The colorspace is unknown + Unknown, + /// Alpha Red Green Blue + ARGB, + /// Hue,Saturation,Lightness + /// Conversion from RGB to HSL and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSL, + /// Hue, Saturation,Value + /// + /// Conversion from RGB to HSV and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module + /// Color type is expected to be in floating point + HSV +} + +impl ColorSpace { + /// Number of color channels present for a certain colorspace + /// + /// E.g. RGB returns 3 since it contains R,G and B colors to make up a pixel + pub const fn num_components(&self) -> usize { + match self { + Self::RGB | Self::YCbCr | Self::BGR | Self::HSV | Self::HSL => 3, + Self::RGBA | Self::YCCK | Self::CMYK | Self::BGRA | Self::ARGB => 4, + Self::Luma => 1, + Self::LumaA => 2, + Self::Unknown => 0 + } + } + + pub const fn has_alpha(&self) -> bool { + matches!(self, Self::RGBA | Self::LumaA | Self::BGRA | Self::ARGB) + } + + pub const fn is_grayscale(&self) -> bool { + matches!(self, Self::LumaA | Self::Luma) + } + + /// Returns the position of the alpha pixel in a pixel + /// + /// + /// That is for an array of color components say `[0,1,2,3]` if the image has an alpha channel + /// and is in RGBA format, this will return `Some(3)`, indicating alpha is found in the third index + /// but if the image is in `ARGB` format, it will return `Some(0)` indicating alpha is found in + /// index 0 + /// + /// If an image doesn't have an alpha channel returns `None` + /// + pub const fn alpha_position(&self) -> Option { + match self { + ColorSpace::RGBA => Some(3), + ColorSpace::LumaA => Some(1), + ColorSpace::BGRA => Some(3), + ColorSpace::ARGB => Some(0), + _ => None + } + } +} + +/// Encapsulates all colorspaces supported by +/// the library +pub static ALL_COLORSPACES: [ColorSpace; 12] = [ + ColorSpace::RGB, + ColorSpace::RGBA, + ColorSpace::LumaA, + ColorSpace::Luma, + ColorSpace::CMYK, + ColorSpace::BGRA, + ColorSpace::BGR, + ColorSpace::YCCK, + ColorSpace::YCbCr, + ColorSpace::ARGB, + ColorSpace::HSL, + ColorSpace::HSV +]; + +/// Color characteristics +/// +/// Gives more information about values in a certain +/// colorspace +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ColorCharacteristics { + /// Normal default gamma setting + /// The float contains gamma present + /// + /// The default gamma value is 2.2 but for + /// decoders that allow specifying gamma values,e.g PNG, + /// the gamma value becomes the specified value by the decoder + sRGB, + /// Linear transfer characteristics + /// The image is in linear colorspace + Linear +} +/// Represents a single channel color primary. +/// +/// This can be viewed as a 3D coordinate of the color primary +/// for a given colorspace +#[derive(Default, Debug, Copy, Clone)] +pub struct SingleColorPrimary { + pub x: f64, + pub y: f64, + pub z: f64 +} +/// A collection of red,green and blue color primaries placed +/// in one struct for easy manipulation +#[derive(Default, Debug, Copy, Clone)] +pub struct ColorPrimaries { + /// Red color primaries + pub red: SingleColorPrimary, + /// Green color primaries + pub green: SingleColorPrimary, + /// Blue color primaries + pub blue: SingleColorPrimary +} + +/// Rendering intents indicate what one may want to do with colors outside of it's gamut +/// +/// +/// Further reading +/// - [IBM Rendering Intent](https://www.ibm.com/docs/en/i/7.5?topic=management-rendering-intents) +/// - [ColorGate Blog](https://blog.colorgate.com/en/rendering-intent-explained) +#[derive(Eq, PartialEq, Clone, Copy, Debug)] +pub enum RenderingIntent { + AbsoluteColorimetric, + Saturation, + RelativeColorimetric, + Perceptual +} diff --git a/third_party/zune-core/src/lib.rs b/third_party/zune-core/src/lib.rs new file mode 100644 index 0000000..77355f9 --- /dev/null +++ b/third_party/zune-core/src/lib.rs @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Core routines shared by all libraries +//! +//! This crate provides a set of core routines shared +//! by the decoders and encoders under `zune` umbrella +//! +//! It currently contains +//! +//! - A bytestream reader and writer with endian aware reads and writes +//! - Colorspace and bit depth information shared by images +//! - Image decoder and encoder options +//! - A simple enum type to hold image decoding results. +//! +//! This library is `#[no_std]` with `alloc` feature needed for defining `Vec` +//! which we need for storing decoded bytes. +//! +//! +//! # Features +//! - `no_std`: Enables `#[no_std]` compilation support. +//! +//! - `serde`: Enables serializing of some of the data structures +//! present in the crate +//! +//! +//! # Input/Output +//! +//! zune-image supports many different input and output devices. For input readers +//! we can read anything that implements `BufRead` + `Seek` and provide an optimized routine for +//! handling in memory buffers by using [`ZCursor`](crate::bytestream::ZCursor). +//! +//! For output, we support anything that implements `Write` trait, this includes files, standard io streams +//! network sockets, etc +//! +//! In a `no_std` environment. We can write to in memory buffers `&mut [u8]` and `&mut Vec` +//! +//! If you have an in memory buffer, use [`ZCursor`](crate::bytestream::ZCursor), +//! it's optimized for in memory buffers. +//! +//! +//! +#![cfg_attr(not(feature = "std"), no_std)] +#![macro_use] +extern crate alloc; +extern crate core; + +#[cfg(not(feature = "log"))] +pub mod log; + +#[cfg(feature = "log")] +pub use log; + +pub mod bit_depth; +pub mod bytestream; +pub mod colorspace; +pub mod options; +pub mod result; +mod serde; diff --git a/third_party/zune-core/src/log.rs b/third_party/zune-core/src/log.rs new file mode 100644 index 0000000..19c867c --- /dev/null +++ b/third_party/zune-core/src/log.rs @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +// #[macro_export] is required to make macros works across crates +// but it always put the macro in the crate root. +// #[doc(hidden)] + "pub use" is a workaround to namespace a macro. +pub use crate::{ + __debug as debug, __error as error, __info as info, __log_enabled as log_enabled, + __trace as trace, __warn as warn +}; + +#[repr(usize)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub enum Level { + Error = 1, + Warn, + Info, + Debug, + Trace +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_enabled { + ($lvl:expr) => {{ + let _ = $lvl; + false + }}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __error { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __warn { + ($($arg:tt)+) => { + #[cfg(feature = "std")] + { + //eprintln!($($arg)+); + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __info { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __debug { + ($($arg:tt)+) => {}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __trace { + ($($arg:tt)+) => {}; +} diff --git a/third_party/zune-core/src/options.rs b/third_party/zune-core/src/options.rs new file mode 100644 index 0000000..59566af --- /dev/null +++ b/third_party/zune-core/src/options.rs @@ -0,0 +1,13 @@ +//! Decoder and Encoder Options +//! +//! This module exposes a struct for which all implemented +//! decoders get shared options for decoding +//! +//! All supported options are put into one _Options to allow for global configurations +//! options e.g the same `DecoderOption` can be reused for all other decoders +//! +pub use decoder::DecoderOptions; +pub use encoder::EncoderOptions; + +mod decoder; +mod encoder; diff --git a/third_party/zune-core/src/options/decoder.rs b/third_party/zune-core/src/options/decoder.rs new file mode 100644 index 0000000..6093c70 --- /dev/null +++ b/third_party/zune-core/src/options/decoder.rs @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Global Decoder options +#![allow(clippy::zero_prefixed_literal)] + +use crate::bit_depth::ByteEndian; +use crate::colorspace::ColorSpace; + +/// A decoder that can handle errors +fn decoder_error_tolerance_mode() -> DecoderFlags { + // similar to fast options currently, so no need to write a new one + fast_options() +} +/// Fast decoder options +/// +/// Enables all intrinsics + unsafe routines +/// +/// Disables png adler and crc checking. +fn fast_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Command line options error resilient and fast +/// +/// Features +/// - Ignore CRC and Adler in png +/// - Do not error out on non-conformance in jpg +/// - Use unsafe paths +fn cmd_options() -> DecoderFlags { + DecoderFlags { + inflate_confirm_adler: false, + png_confirm_crc: false, + jpg_error_on_non_conformance: false, + + zune_use_unsafe: true, + zune_use_neon: true, + zune_use_avx: true, + zune_use_avx2: true, + zune_use_sse2: true, + zune_use_sse3: true, + zune_use_sse41: true, + + png_add_alpha_channel: false, + png_strip_16_bit_to_8_bit: false, + + png_decode_animated: true, + jxl_decode_animated: true + } +} + +/// Decoder options that are flags +/// +/// NOTE: When you extend this, add true or false to +/// all options above that return a `DecoderFlag` +#[derive(Copy, Debug, Clone, Default)] +pub struct DecoderFlags { + /// Whether the decoder should confirm and report adler mismatch + inflate_confirm_adler: bool, + /// Whether the PNG decoder should confirm crc + png_confirm_crc: bool, + /// Whether the png decoder should error out on image non-conformance + jpg_error_on_non_conformance: bool, + /// Whether the decoder should use unsafe platform specific intrinsics + /// + /// This will also shut down platform specific intrinsics `(ZUNE_USE_{EXT})` value + zune_use_unsafe: bool, + /// Whether we should use SSE2. + /// + /// This should be enabled for all x64 platforms but can be turned off if + /// `ZUNE_USE_UNSAFE` is false + zune_use_sse2: bool, + /// Whether we should use SSE3 instructions where possible. + zune_use_sse3: bool, + /// Whether we should use sse4.1 instructions where possible. + zune_use_sse41: bool, + /// Whether we should use avx instructions where possible. + zune_use_avx: bool, + /// Whether we should use avx2 instructions where possible. + zune_use_avx2: bool, + /// Whether the png decoder should add alpha channel where possible. + png_add_alpha_channel: bool, + /// Whether we should use neon instructions where possible. + zune_use_neon: bool, + /// Whether the png decoder should strip 16 bit to 8 bit + png_strip_16_bit_to_8_bit: bool, + /// Decode all frames for an animated images + png_decode_animated: bool, + jxl_decode_animated: bool +} + +/// Decoder options +/// +/// Not all options are respected by decoders all decoders +#[derive(Debug, Copy, Clone)] +pub struct DecoderOptions { + /// Maximum width for which decoders will + /// not try to decode images larger than + /// the specified width. + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_width: usize, + /// Maximum height for which decoders will not + /// try to decode images larger than the + /// specified height + /// + /// - Default value: 16384 + /// - Respected by: `all decoders` + max_height: usize, + /// Output colorspace + /// + /// The jpeg decoder allows conversion to a separate colorspace + /// than the input. + /// + /// I.e you can convert a RGB jpeg image to grayscale without + /// first decoding it to RGB to get + /// + /// - Default value: `ColorSpace::RGB` + /// - Respected by: `jpeg` + out_colorspace: ColorSpace, + + /// Maximum number of scans allowed + /// for progressive jpeg images + /// + /// Progressive jpegs have scans + /// + /// - Default value:100 + /// - Respected by: `jpeg` + max_scans: usize, + /// Maximum size for deflate. + /// Respected by all decoders that use inflate/deflate + deflate_limit: usize, + /// Boolean flags that influence decoding + flags: DecoderFlags, + /// The byte endian of the returned bytes will be stored in + /// in case a single pixel spans more than a byte + endianness: ByteEndian +} + +/// Initializers +impl DecoderOptions { + /// Create the decoder with options setting most configurable + /// options to be their safe counterparts + /// + /// This is the same as `default` option as default initializes + /// options to the safe variant. + /// + /// Note, decoders running on this will be slower as it disables + /// platform specific intrinsics + pub fn new_safe() -> DecoderOptions { + DecoderOptions::default() + } + + /// Create the decoder with options setting the configurable options + /// to the fast counterparts + /// + /// This enables platform specific code paths and enable use of unsafe + pub fn new_fast() -> DecoderOptions { + let flag = fast_options(); + DecoderOptions::default().set_decoder_flags(flag) + } + + /// Create the decoder options with the following characteristics + /// + /// - Use unsafe paths. + /// - Ignore error checksuming, e.g in png we do not confirm adler and crc in this mode + /// - Enable fast intrinsics paths + pub fn new_cmd() -> DecoderOptions { + let flag = cmd_options(); + DecoderOptions::default().set_decoder_flags(flag) + } +} + +/// Global options respected by all decoders +impl DecoderOptions { + /// Get maximum width configured for which the decoder + /// should not try to decode images greater than this width + pub const fn max_width(&self) -> usize { + self.max_width + } + + /// Get maximum height configured for which the decoder should + /// not try to decode images greater than this height + pub const fn max_height(&self) -> usize { + self.max_height + } + + /// Return true whether the decoder should be in strict mode + /// And reject most errors + pub fn strict_mode(&self) -> bool { + self.flags.jpg_error_on_non_conformance + | self.flags.png_confirm_crc + | self.flags.inflate_confirm_adler + } + /// Return true if the decoder should use unsafe + /// routines where possible + pub const fn use_unsafe(&self) -> bool { + self.flags.zune_use_unsafe + } + + /// Set maximum width for which the decoder should not try + /// decoding images greater than that width + /// + /// # Arguments + /// + /// * `width`: The maximum width allowed + /// + /// returns: DecoderOptions + pub fn set_max_width(mut self, width: usize) -> Self { + self.max_width = width; + self + } + + /// Set maximum height for which the decoder should not try + /// decoding images greater than that height + /// # Arguments + /// + /// * `height`: The maximum height allowed + /// + /// returns: DecoderOptions + /// + pub fn set_max_height(mut self, height: usize) -> Self { + self.max_height = height; + self + } + + /// Whether the routines can use unsafe platform specific + /// intrinsics when necessary + /// + /// Platform intrinsics are implemented for operations which + /// the compiler can't auto-vectorize, or we can do a marginably + /// better job at it + /// + /// All decoders with unsafe routines respect it. + /// + /// Treat this with caution, disabling it will cause slowdowns but + /// it's provided for mainly for debugging use. + /// + /// - Respected by: `png` and `jpeg`(decoders with unsafe routines) + pub fn set_use_unsafe(mut self, yes: bool) -> Self { + // first clear the flag + self.flags.zune_use_unsafe = yes; + self + } + + fn set_decoder_flags(mut self, flags: DecoderFlags) -> Self { + self.flags = flags; + self + } + /// Set whether the decoder should be in standards conforming/ + /// strict mode + /// + /// This reduces the error tolerance level for the decoders and invalid + /// samples will be rejected by the decoder + /// + /// # Arguments + /// + /// * `yes`: + /// + /// returns: DecoderOptions + /// + pub fn set_strict_mode(mut self, yes: bool) -> Self { + self.flags.jpg_error_on_non_conformance = yes; + self.flags.png_confirm_crc = yes; + self.flags.inflate_confirm_adler = yes; + self + } + + /// Set the byte endian for which raw samples will be stored in + /// in case a single pixel sample spans more than a byte. + /// + /// The default is usually native endian hence big endian values + /// will be converted to little endian on little endian systems, + /// + /// and little endian values will be converted to big endian on big endian systems + /// + /// # Arguments + /// + /// * `endian`: The endianness to which to set the bytes to + /// + /// returns: DecoderOptions + pub fn set_byte_endian(mut self, endian: ByteEndian) -> Self { + self.endianness = endian; + self + } + + /// Get the byte endian for which samples that span more than one byte will + /// be treated + pub const fn byte_endian(&self) -> ByteEndian { + self.endianness + } +} + +/// PNG specific options +impl DecoderOptions { + /// Whether the inflate decoder should confirm + /// adler checksums + pub const fn inflate_get_confirm_adler(&self) -> bool { + self.flags.inflate_confirm_adler + } + /// Set whether the inflate decoder should confirm + /// adler checksums + pub fn inflate_set_confirm_adler(mut self, yes: bool) -> Self { + self.flags.inflate_confirm_adler = yes; + self + } + /// Get default inflate limit for which the decoder + /// will not try to decompress further + pub const fn inflate_get_limit(&self) -> usize { + self.deflate_limit + } + /// Set the default inflate limit for which decompressors + /// relying on inflate won't surpass this limit + #[must_use] + pub fn inflate_set_limit(mut self, limit: usize) -> Self { + self.deflate_limit = limit; + self + } + /// Whether the inflate decoder should confirm + /// crc 32 checksums + pub const fn png_get_confirm_crc(&self) -> bool { + self.flags.png_confirm_crc + } + /// Set whether the png decoder should confirm + /// CRC 32 checksums + #[must_use] + pub fn png_set_confirm_crc(mut self, yes: bool) -> Self { + self.flags.png_confirm_crc = yes; + self + } + /// Set whether the png decoder should add an alpha channel to + /// images where possible. + /// + /// For Luma images, it converts it to Luma+Alpha + /// + /// For RGB images it converts it to RGB+Alpha + pub fn png_set_add_alpha_channel(mut self, yes: bool) -> Self { + self.flags.png_add_alpha_channel = yes; + self + } + /// Return true whether the png decoder should add an alpha + /// channel to images where possible + pub const fn png_get_add_alpha_channel(&self) -> bool { + self.flags.png_add_alpha_channel + } + + /// Whether the png decoder should reduce 16 bit images to 8 bit + /// images implicitly. + /// + /// Equivalent to [png::Transformations::STRIP_16](https://docs.rs/png/latest/png/struct.Transformations.html#associatedconstant.STRIP_16) + pub fn png_set_strip_to_8bit(mut self, yes: bool) -> Self { + self.flags.png_strip_16_bit_to_8_bit = yes; + self + } + + /// Return a boolean indicating whether the png decoder should reduce + /// 16 bit images to 8 bit images implicitly + pub const fn png_get_strip_to_8bit(&self) -> bool { + self.flags.png_strip_16_bit_to_8_bit + } + + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_decode_animated(&self) -> bool { + self.flags.png_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn png_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.png_decode_animated = yes; + self + } +} + +/// JPEG specific options +impl DecoderOptions { + /// Get maximum scans for which the jpeg decoder + /// should not go above for progressive images + pub const fn jpeg_get_max_scans(&self) -> usize { + self.max_scans + } + + /// Set maximum scans for which the jpeg decoder should + /// not exceed when reconstructing images. + pub fn jpeg_set_max_scans(mut self, max_scans: usize) -> Self { + self.max_scans = max_scans; + self + } + /// Get expected output colorspace set by the user for which the image + /// is expected to be reconstructed into. + /// + /// This may be different from the + pub const fn jpeg_get_out_colorspace(&self) -> ColorSpace { + self.out_colorspace + } + /// Set expected colorspace for which the jpeg output is expected to be in + /// + /// This is mainly provided as is, we do not guarantee the decoder can convert to all colorspaces + /// and the decoder can change it internally when it sees fit. + #[must_use] + pub fn jpeg_set_out_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.out_colorspace = colorspace; + self + } +} + +/// Intrinsics support +/// +/// These routines are compiled depending +/// on the platform they are used, if compiled for a platform +/// it doesn't support,(e.g avx2 on Arm), it will always return `false` +impl DecoderOptions { + /// Use SSE 2 code paths where possible + /// + /// This checks for existence of SSE2 first and returns + /// false if it's not present + #[allow(unreachable_code)] + pub fn use_sse2(&self) -> bool { + let opt = self.flags.zune_use_sse2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse2") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse2"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE 3 paths where possible + /// + /// + /// This also checks for SSE3 support and returns false if + /// it's not present + #[allow(unreachable_code)] + pub fn use_sse3(&self) -> bool { + let opt = self.flags.zune_use_sse3 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse3") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse3"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use SSE4 paths where possible + /// + /// This also checks for sse 4.1 support and returns false if it + /// is not present + #[allow(unreachable_code)] + pub fn use_sse41(&self) -> bool { + let opt = self.flags.zune_use_sse41 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("sse4.1") { + return true; + } + } + // where we can't do runtime check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "sse4.1"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use AVX paths where possible + /// + /// This also checks for AVX support and returns false if it's + /// not present + #[allow(unreachable_code)] + pub fn use_avx(&self) -> bool { + let opt = self.flags.zune_use_avx | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx"))] + { + return true; + } + } + // everything failed return false + false + } + + /// Use avx2 paths where possible + /// + /// This also checks for AVX2 support and returns false if it's not + /// present + #[allow(unreachable_code)] + pub fn use_avx2(&self) -> bool { + let opt = self.flags.zune_use_avx2 | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + { + // where we can do runtime check if feature is present + #[cfg(feature = "std")] + { + if is_x86_feature_detected!("avx2") { + return true; + } + } + // where we can't do runitme check if feature is present + // check if the compile feature had it enabled + #[cfg(all(not(feature = "std"), target_feature = "avx2"))] + { + return true; + } + } + // everything failed return false + false + } + + #[allow(unreachable_code)] + pub fn use_neon(&self) -> bool { + let opt = self.flags.zune_use_neon | self.flags.zune_use_unsafe; + // options says no + if !opt { + return false; + } + + #[cfg(target_arch = "aarch64")] + { + // aarch64 implies neon on a compliant cpu + // but for real prod should do something better here + return true; + } + // everything failed return false + false + } +} + +/// JPEG_XL specific options +impl DecoderOptions { + /// Return whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_decode_animated(&self) -> bool { + self.flags.jxl_decode_animated + } + /// Set whether `zune-image` should decode animated images or + /// whether we should just decode the first frame only + pub const fn jxl_set_decode_animated(mut self, yes: bool) -> Self { + self.flags.jxl_decode_animated = yes; + self + } +} +impl Default for DecoderOptions { + /// Create a default and sane option for decoders + /// + /// The following are the defaults + /// + /// - All decoders + /// - max_width: 16536 + /// - max_height: 16535 + /// - use_unsafe: Use unsafe intrinsics where possible. + /// + /// - JPEG + /// - max_scans: 100 (progressive images only, artificial cap to prevent a specific DOS) + /// - error_on_non_conformance: False (slightly corrupt images will be allowed) + /// - DEFLATE + /// - deflate_limit: 1GB (will not continue decoding deflate archives larger than this) + /// - PNG + /// - endianness: Default endianess is Big Endian when decoding 16 bit images to be viewed as 8 byte images + /// - confirm_crc: False (CRC will not be confirmed to be safe) + /// - strip_16_bit_to_8: False, 16 bit images are handled as 16 bit images + /// - add alpha: False, alpha channel is not added where it isn't present + /// - decode_animated: True: All frames in an animated image are decoded + /// + /// - JXL + /// - decode_animated: True: All frames in an animated image are decoded + /// + fn default() -> Self { + Self { + out_colorspace: ColorSpace::RGB, + max_width: 1 << 14, + max_height: 1 << 14, + max_scans: 100, + deflate_limit: 1 << 30, + flags: decoder_error_tolerance_mode(), + endianness: ByteEndian::BE + } + } +} diff --git a/third_party/zune-core/src/options/encoder.rs b/third_party/zune-core/src/options/encoder.rs new file mode 100644 index 0000000..fb59f6c --- /dev/null +++ b/third_party/zune-core/src/options/encoder.rs @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use crate::bit_depth::BitDepth; +use crate::colorspace::ColorSpace; + +/// Encoder options that are flags +#[derive(Copy, Debug, Clone, Default)] +struct EncoderFlags { + /// Whether JPEG images should be encoded as progressive images + jpeg_encode_progressive: bool, + /// Whether JPEG images should use optimized huffman tables + jpeg_optimize_huffman: bool, + /// Whether to not preserve metadata across image transformations + image_strip_metadata: bool +} + +/// Options shared by some of the encoders in +/// the `zune-` family of image crates +#[derive(Debug, Copy, Clone)] +pub struct EncoderOptions { + width: usize, + height: usize, + colorspace: ColorSpace, + quality: u8, + depth: BitDepth, + num_threads: u8, + effort: u8, + flags: EncoderFlags +} + +impl Default for EncoderOptions { + fn default() -> Self { + Self { + width: 0, + height: 0, + colorspace: ColorSpace::RGB, + quality: 80, + depth: BitDepth::Eight, + num_threads: 4, + effort: 4, + flags: EncoderFlags::default() + } + } +} + +impl EncoderOptions { + /// Create new encode options + /// + /// # Arguments + /// + /// * `width`: Image width + /// * `height`: Image height + /// * `colorspace`: Image colorspaces + /// * `depth`: Image depth + /// + /// returns: EncoderOptions + /// + pub fn new( + width: usize, height: usize, colorspace: ColorSpace, depth: BitDepth + ) -> EncoderOptions { + EncoderOptions { + width, + height, + colorspace, + depth, + ..Default::default() + } + } + /// Get the width for which the image will be encoded in + pub const fn width(&self) -> usize { + self.width + } + + /// Get height for which the image will be encoded in + /// + /// returns: usize + /// + /// # Panics + /// If height is zero + pub fn height(&self) -> usize { + assert_ne!(self.height, 0); + self.height + } + /// Get the depth for which the image will be encoded in + pub const fn depth(&self) -> BitDepth { + self.depth + } + /// Get the quality for which the image will be encoded with + /// + /// # Lossy + /// - Higher quality means some images take longer to write and + /// are big but they look good + /// + /// - Lower quality means small images and low quality. + /// + /// # Lossless + /// - High quality indicates more time is spent in making the file + /// smaller + /// + /// - Low quality indicates less time is spent in making the file bigger + pub const fn quality(&self) -> u8 { + self.quality + } + /// Get the colorspace for which the image will be encoded in + pub const fn colorspace(&self) -> ColorSpace { + self.colorspace + } + pub const fn effort(&self) -> u8 { + self.effort + } + + /// Set width for the image to be encoded + pub fn set_width(mut self, width: usize) -> Self { + self.width = width; + self + } + + /// Set height for the image to be encoded + pub fn set_height(mut self, height: usize) -> Self { + self.height = height; + self + } + /// Set depth for the image to be encoded + pub fn set_depth(mut self, depth: BitDepth) -> Self { + self.depth = depth; + self + } + /// Set quality of the image to be encoded + /// + /// Quality is clamped from 0..100 + /// + /// Quality means different options depending on the encoder, see + /// [get_quality](Self::quality) + pub fn set_quality(mut self, quality: u8) -> Self { + self.quality = quality.clamp(0, 100); + self + } + /// Set colorspace for the image to be encoded + pub fn set_colorspace(mut self, colorspace: ColorSpace) -> Self { + self.colorspace = colorspace; + self + } + /// Set the number of threads allowed for multithreaded encoding + /// where supported + /// + /// Zero means use a single thread + pub fn set_num_threads(mut self, threads: u8) -> Self { + self.num_threads = threads; + + self + } + pub fn set_effort(mut self, effort: u8) -> Self { + self.effort = effort; + self + } + + /// Return number of threads configured for multithreading + /// where possible + /// + /// This is used for multi-threaded encoders, + /// currently only jpeg-xl + pub const fn num_threads(&self) -> u8 { + self.num_threads + } + + /// Set whether the encoder should remove metadata from the image + /// + /// When set to `true`, supported encoders will strip away metadata + /// from the resulting image. If set to false, where supported, encoders + /// will not remove metadata from images + pub fn set_strip_metadata(mut self, yes: bool) -> Self { + self.flags.image_strip_metadata = yes; + self + } + /// Whether or not the encoder should remove metadata from the image + /// + /// The default value is false, and encoders that respect this try to preserve as much + /// data as possible from one image to another + pub const fn strip_metadata(&self) -> bool { + !self.flags.image_strip_metadata + } +} + +/// JPEG options +impl EncoderOptions { + /// Whether the jpeg encoder should encode the image in progressive mode + /// + /// Default is `false`. + /// + /// This may be used to create slightly smaller images at the cost of more processing + /// time + pub const fn jpeg_encode_progressive(&self) -> bool { + self.flags.jpeg_encode_progressive + } + + /// Whether the jpeg encoder should optimize huffman tables to create smaller files + /// at the cost of processing time + /// + /// Default is `false`. + pub const fn jpeg_optimized_huffman_tables(&self) -> bool { + self.flags.jpeg_optimize_huffman + } + + /// Set whether the jpeg encoder should encode the imagei in progressive mode + /// + /// Default is `false` + pub fn set_jpeg_encode_progressive(mut self, yes: bool) -> Self { + self.flags.jpeg_optimize_huffman = yes; + self + } +} diff --git a/third_party/zune-core/src/result.rs b/third_party/zune-core/src/result.rs new file mode 100644 index 0000000..135bfb9 --- /dev/null +++ b/third_party/zune-core/src/result.rs @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decoding results for images +use alloc::vec::Vec; + +/// A simple enum that can hold decode +/// results of most images +#[non_exhaustive] +pub enum DecodingResult { + U8(Vec), + U16(Vec), + F32(Vec) +} + +impl DecodingResult { + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this won't fail because we created it with u8 + /// assert!(data.u8().is_some()); + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return nothing since the type is u18 + /// assert!(data.u8().is_none()); + /// + /// ``` + pub fn u8(self) -> Option> { + match self { + DecodingResult::U8(data) => Some(data), + _ => None + } + } + + /// Return the contents if the enum stores `Vec` or otherwise + /// return `None`. + /// + /// Useful for de-sugaring the result of a decoding operation + /// into raw bytes + /// + /// # Example + /// ``` + /// use zune_core::result::DecodingResult; + /// let data = DecodingResult::U8(vec![0;100]); + /// // we know this will fail because we created it with u16 + /// assert!(data.u16().is_none()); + /// + /// + /// let data = DecodingResult::U16(vec![0;100]); + /// // it should now return something since the type is u16 + /// assert!(data.u16().is_some()); + /// + /// ``` + pub fn u16(self) -> Option> { + match self { + DecodingResult::U16(data) => Some(data), + _ => None + } + } +} diff --git a/third_party/zune-core/src/serde.rs b/third_party/zune-core/src/serde.rs new file mode 100644 index 0000000..0e3b1f3 --- /dev/null +++ b/third_party/zune-core/src/serde.rs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(feature = "serde")] +//! Serde support for serializing +//! crate datastructures +//! +//! Implements serialize for +//! - ColorSpace +//! - BitDepth +//! - ColorCharacteristics +use alloc::format; + +use serde::ser::*; + +use crate::bit_depth::BitDepth; +use crate::colorspace::{ColorCharacteristics, ColorSpace, RenderingIntent}; + +impl Serialize for ColorSpace { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + // colorspace serialization is simply it's debug value + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for BitDepth { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for ColorCharacteristics { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} + +impl Serialize for RenderingIntent { + #[allow(clippy::uninlined_format_args)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer + { + serializer.serialize_str(&format!("{:?}", self)) + } +} diff --git a/third_party/zune-jpeg/.gitignore b/third_party/zune-jpeg/.gitignore new file mode 100644 index 0000000..c41cc9e --- /dev/null +++ b/third_party/zune-jpeg/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/third_party/zune-jpeg/Benches.md b/third_party/zune-jpeg/Benches.md new file mode 100644 index 0000000..296e96a --- /dev/null +++ b/third_party/zune-jpeg/Benches.md @@ -0,0 +1,79 @@ +# Benchmarks of popular jpeg libraries + +Here I compare how long it takes popular JPEG decoders to decode the below 7680*4320 image +of (now defunct ?) [Cutefish OS](https://en.cutefishos.com/) default wallpaper. +![img](benches/images/speed_bench.jpg) + +## About benchmarks + +Benchmarks are weird, especially IO & multi-threaded programs. This library uses both of the above hence performance may +vary. + +For best results shut down your machine, go take coffee, think about life and how it came to be and why people should +save the environment. + +Then power up your machine, if it's a laptop connect it to a power supply and if there is a setting for performance +mode, tweak it. + +Then run. + +## Benchmarks vs real world usage + +Real world usage may vary. + +Notice that I'm using a large image but probably most decoding will be small to medium images. + +To make the library thread safe, we do about 1.5-1.7x more allocations than libjpeg-turbo. Although, do note that the +allocations do not occur at ago, we allocate when needed and deallocate when not needed. + +Do note if memory bandwidth is a limitation. This is not for you. + +## Reproducibility + +The benchmarks are carried out on my local machine with an AMD Ryzen 5 4500u + +The benchmarks are reproducible. + +To reproduce them + +1. Clone this repository +2. Install rust(if you don't have it yet) +3. `cd` into the directory. +4. Run `cargo bench` + +## Performance features of the three libraries + +| feature | image-rs/jpeg-decoder | libjpeg-turbo | zune-jpeg | +|------------------------------|-----------------------|---------------|-----------| +| multithreaded | ✅ | ❌ | ❌ | +| platform specific intrinsics | ✅ | ✅ | ✅ | + +- Image-rs/jpeg-decoder uses [rayon] under the hood but it's under a feature + flag. + +- libjpeg-turbo uses hand-written asm for platform specific intrinsics, ported to + the most common architectures out there but falls back to scalar + code if it can't run in a platform. + +# Finally benchmarks + +[here] + +## Notes + +Benchmarks are ran at least once a week to catch regressions early and +are uploaded to Github pages. + +Machine specs can be found on the other [landing page] + +Benchmarks may not reflect real world usage(threads, other I/O machine bottlenecks) + +[landing page]:https://etemesi254.github.io/posts/Zune-Benchmarks/ + +[here]:https://etemesi254.github.io/assets/criterion/report/index.html + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo + +[jpeg-decoder]:https://github.com/image-rs/jpeg-decoder + +[rayon]:https://github.com/rayon-rs/rayon \ No newline at end of file diff --git a/third_party/zune-jpeg/Cargo.toml b/third_party/zune-jpeg/Cargo.toml new file mode 100644 index 0000000..1f6a884 --- /dev/null +++ b/third_party/zune-jpeg/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "zune-jpeg" +version = "0.5.0-rc1" +authors = ["caleb "] +edition = "2021" +repository = "https://github.com/etemesi254/zune-image/tree/dev/crates/zune-jpeg" +license = "MIT OR Apache-2.0 OR Zlib" +keywords = ["jpeg", "jpeg-decoder", "decoder"] +categories = ["multimedia::images"] +exclude = ["/benches/images/*", "/tests/*", "/.idea/*", "/.gradle/*", "/test-images/*", "fuzz/*"] +description = "A fast, correct and safe jpeg decoder" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +x86 = [] +neon = [] +std = ["zune-core/std"] +log = ["zune-core/log"] +default = ["x86", "neon", "std"] + +[dependencies] +zune-core = { path = "../zune-core", version = "^0.5.0-rc1" } + + +[dev-dependencies] +zune-ppm = { path = "../zune-ppm" } diff --git a/third_party/zune-jpeg/Changelog.md b/third_party/zune-jpeg/Changelog.md new file mode 100644 index 0000000..1a9ec0d --- /dev/null +++ b/third_party/zune-jpeg/Changelog.md @@ -0,0 +1,64 @@ +## Version 0.3.17 + +- Fix no-std compilation + +## Version 0.3.16 + +- Add support for decoding to BGR and BGRA + +## Version 0.3.14 + +- Add ability to parse exif and ICC chunk. +- Fix images with one component that were down-sampled. + +### Version 0.3.13 + +- Allow decoding into pre-allocated buffer +- Clarify documentation + +### Version 0.3.11 + +- Add guards for SSE and AVX code paths(allows compiling for platforms that do not support it) + +### Version 0.3.0 + +- Overhaul to the whole decoder. +- Single threaded version +- Lightweight. + +### Version 0.2.0 + +- New `ZuneJpegOptions` struct, this is the now recommended way to set up decoding options for + decoding +- Deprecated previous options setting functions. +- More code cleanups +- Fixed new bugs discovered by fuzzing +- Removed dependency on `num_cpu` + +### Version 0.1.5 +- Allow user to set memory limits in during decoding explicitly via `set_limits` +- Fixed some bugs discovered by fuzzing +- Correctly handle small images less than 16 pixels +- Gracefully handle incorrectly sampled images. + +### Version 0.1.4 +- Remove all `unsafe` instances except platform dependent intrinsics. +- Numerous bug fixes identified by fuzzing. +- Expose `ImageInfo` to the crate root. + +### Version 0.1.3 +- Fix numerous panics found by fuzzing(thanks to @[Shnatsel] for the corpus) +- Add new method `set_num_threads` that allows one to explicitly set the number of threads to use to decode the image. + +### Version 0.1.2 +- Add more sub checks, contributed by @[5225225] +- Privatize some modules. + +### Version 0.1.1 +- Fix rgba/rgbx decoding when avx optimized functions were used +- Initial support for fuzzing +- Remove `align_alloc` method which was unsound (Thanks to @[HeroicKatora] for pointing that out) + +[Shnatsel]:https://github.com/Shnatsel +[HeroicKatora]:https://github.com/HeroicKatora +[5225225]:https://github.com/5225225 \ No newline at end of file diff --git a/third_party/zune-jpeg/LICENSE-APACHE b/third_party/zune-jpeg/LICENSE-APACHE new file mode 100644 index 0000000..1cd601d --- /dev/null +++ b/third_party/zune-jpeg/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/third_party/zune-jpeg/LICENSE-MIT b/third_party/zune-jpeg/LICENSE-MIT new file mode 100644 index 0000000..b2cfbdc --- /dev/null +++ b/third_party/zune-jpeg/LICENSE-MIT @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/third_party/zune-jpeg/LICENSE-ZLIB b/third_party/zune-jpeg/LICENSE-ZLIB new file mode 100644 index 0000000..f0648a7 --- /dev/null +++ b/third_party/zune-jpeg/LICENSE-ZLIB @@ -0,0 +1 @@ +../../LICENSE-ZLIB \ No newline at end of file diff --git a/third_party/zune-jpeg/README.md b/third_party/zune-jpeg/README.md new file mode 100644 index 0000000..606c987 --- /dev/null +++ b/third_party/zune-jpeg/README.md @@ -0,0 +1,104 @@ +# Zune-JPEG + +A fast, correct and safe jpeg decoder in pure Rust. + +## Usage + +The library provides a simple-to-use API for jpeg decoding +and an ability to add options to influence decoding. + +### Example + +```Rust +// Import the library +use zune_jpeg::JpegDecoder; +use std::fs::read; + +fn main()->Result<(),DecoderErrors> { + // load some jpeg data + let data = read("cat.jpg").unwrap(); + // create a decoder + let mut decoder = JpegDecoder::new(&data); + // decode the file + let pixels = decoder.decode()?; +} +``` + +The decoder supports more manipulations via `DecoderOptions`, +see additional documentation in the library. + +## Goals + +The implementation aims to have the following goals achieved, +in order of importance + +1. Safety - Do not segfault on errors or invalid input. Panics are okay, but + should be fixed when reported. `unsafe` is only used for SIMD intrinsics, + and can be turned off entirely both at compile time and at runtime. +2. Speed - Get the data as quickly as possible, which means + 1. Platform intrinsics code where justifiable + 2. Carefully written platform independent code that allows the + compiler to vectorize it. + 3. Regression tests. + 4. Watch the memory usage of the program +3. Usability - Provide utility functions like different color conversions functions. + +## Non-Goals + +- Bit identical results with libjpeg/libjpeg-turbo will never be an aim of this library. + Jpeg is a lossy format with very few parts specified by the standard + (i.e it doesn't give a reference upsampling and color conversion algorithm) + +## Features + +- [x] A Pretty fast 8*8 integer IDCT. +- [x] Fast Huffman Decoding +- [x] Fast color convert functions. +- [x] Support for extended colorspaces like GrayScale and RGBA +- [X] Single-threaded decoding. +- [X] Support for four component JPEGs, and esoteric color schemes like CYMK +- [X] Support for `no_std` +- [X] BGR/BGRA decoding support. + +## Crate Features + +| feature | on | Capabilities | +|---------|-----|---------------------------------------------------------------------------------------------| +| `x86` | yes | Enables `x86` specific instructions, specifically `avx` and `sse` for accelerated decoding. | +| `std` | yes | Enable linking to the `std` crate | + +Note that the `x86` features are automatically disabled on platforms that aren't x86 during compile +time hence there is no need to disable them explicitly if you are targeting such a platform. + +## Using in a `no_std` environment + +The crate can be used in a `no_std` environment with the `alloc` feature. + +But one is required to link to a working allocator for whatever environment the decoder +will be running on + +## Debug vs release + +The decoder heavily relies on platform specific intrinsics, namely AVX2 and SSE to gain speed-ups in decoding, +but they [perform poorly](https://godbolt.org/z/vPq57z13b) in debug builds. To get reasonable performance even +when compiling your program in debug mode, add this to your `Cargo.toml`: + +```toml +# `zune-jpeg` package will be always built with optimizations +[profile.dev.package.zune-jpeg] +opt-level = 3 +``` + +## Benchmarks + +The library tries to be at fast as [libjpeg-turbo] while being as safe as possible. +Platform specific intrinsics help get speed up intensive operations ensuring we can almost +match [libjpeg-turbo] speeds but speeds are always +- 10 ms of this library. + +For more up-to-date benchmarks, see the online repo with +benchmarks [here](https://etemesi254.github.io/assets/criterion/report/index.html) + + +[libjpeg-turbo]:https://github.com/libjpeg-turbo/libjpeg-turbo/ + +[image-rs/jpeg-decoder]:https://github.com/image-rs/jpeg-decoder/tree/master/src diff --git a/third_party/zune-jpeg/fuzz/.gitignore b/third_party/zune-jpeg/fuzz/.gitignore new file mode 100644 index 0000000..a092511 --- /dev/null +++ b/third_party/zune-jpeg/fuzz/.gitignore @@ -0,0 +1,3 @@ +target +corpus +artifacts diff --git a/third_party/zune-jpeg/fuzz/Cargo.toml b/third_party/zune-jpeg/fuzz/Cargo.toml new file mode 100644 index 0000000..2574dcd --- /dev/null +++ b/third_party/zune-jpeg/fuzz/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "zune-jpeg-fuzz" +version = "0.0.0" +authors = ["Automatically generated"] +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.zune-jpeg] +path = ".." +features = ["neon", "x86"] + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "decode_buffer" +path = "fuzz_targets/decode_buffer.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_idct" +path = "fuzz_targets/fuzz_idct.rs" +test = false +doc = false diff --git a/third_party/zune-jpeg/fuzz/fuzz_targets/decode_buffer.rs b/third_party/zune-jpeg/fuzz/fuzz_targets/decode_buffer.rs new file mode 100644 index 0000000..6f2e206 --- /dev/null +++ b/third_party/zune-jpeg/fuzz/fuzz_targets/decode_buffer.rs @@ -0,0 +1,10 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + use zune_jpeg::zune_core::bytestream::ZCursor; + let data = ZCursor::new(data); + let mut decoder = zune_jpeg::JpegDecoder::new(data); + let _ = decoder.decode(); +}); diff --git a/third_party/zune-jpeg/fuzz/fuzz_targets/fuzz_idct.rs b/third_party/zune-jpeg/fuzz/fuzz_targets/fuzz_idct.rs new file mode 100644 index 0000000..8fa03ad --- /dev/null +++ b/third_party/zune-jpeg/fuzz/fuzz_targets/fuzz_idct.rs @@ -0,0 +1,47 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; +use zune_jpeg::idct::scalar::idct_int; + +fuzz_target!(|data: [i32; 64]| { + let mut data = data; + + // keep in some relatively sane range + // to prevent scalar overflows + for d in &mut data + { + let bound = 255; + *d = (*d).min(bound).max(-bound); + } + let mut data_vec = data; + // this is way too big but it shouldn't matter + // scalar and vector should mutate the minimum needed + + let mut output_scalar = [0i16; 64]; + let mut output_vector = [0i16; 64]; + + let _must_use_supported_vector_arch; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(target_feature = "avx2")] + { + use zune_jpeg::idct::avx2::idct_avx2; + idct_avx2(&mut data_vec, &mut output_vector, 8); + _must_use_supported_vector_arch = true; + } + + #[cfg(target_arch = "aarch64")] + { + use zune_jpeg::idct::neon::idct_neon; + idct_neon(&mut data_vec, &mut output_vector, 8); + _must_use_supported_vector_arch = true; + } + + if _must_use_supported_vector_arch + { + idct_int(&mut data, &mut output_scalar, 8); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + else + { + panic!("No vector IDCT ran!") + } +}); diff --git a/third_party/zune-jpeg/src/bitstream.rs b/third_party/zune-jpeg/src/bitstream.rs new file mode 100644 index 0000000..9f3032a --- /dev/null +++ b/third_party/zune-jpeg/src/bitstream.rs @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::if_not_else, + clippy::similar_names, + clippy::inline_always, + clippy::doc_markdown, + clippy::cast_sign_loss, + clippy::cast_possible_truncation +)] + +//! This file exposes a single struct that can decode a huffman encoded +//! Bitstream in a JPEG file +//! +//! This code is optimized for speed. +//! It's meant to be super duper super fast, because everyone else depends on this being fast. +//! It's (annoyingly) serial hence we cant use parallel bitstreams(it's variable length coding.) +//! +//! Furthermore, on the case of refills, we have to do bytewise processing because the standard decided +//! that we want to support markers in the middle of streams(seriously few people use RST markers). +//! +//! So we pull in all optimization steps: +//! - use `inline[always]`? ✅ , +//! - pre-execute most common cases ✅, +//! - add random comments ✅ +//! - fast paths ✅. +//! +//! Speed-wise: It is probably the fastest JPEG BitStream decoder to ever sail the seven seas because of +//! a couple of optimization tricks. +//! 1. Fast refills from libjpeg-turbo +//! 2. As few as possible branches in decoder fast paths. +//! 3. Accelerated AC table decoding borrowed from stb_image.h written by Fabian Gissen (@ rygorous), +//! improved by me to handle more cases. +//! 4. Safe and extensible routines(e.g. cool ways to eliminate bounds check) +//! 5. No unsafe here +//! +//! Readability comes as a second priority(I tried with variable names this time, and we are wayy better than libjpeg). +//! +//! Anyway if you are reading this it means your cool and I hope you get whatever part of the code you are looking for +//! (or learn something cool) +//! +//! Knock yourself out. +use alloc::format; +use alloc::string::ToString; +use core::cmp::min; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; + +use crate::errors::DecodeErrors; +use crate::huffman::{HuffmanTable, HUFF_LOOKAHEAD}; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::UN_ZIGZAG; + +macro_rules! decode_huff { + ($stream:tt,$symbol:tt,$table:tt) => { + let mut code_length = $symbol >> HUFF_LOOKAHEAD; + + ($symbol) &= (1 << HUFF_LOOKAHEAD) - 1; + + if code_length > i32::from(HUFF_LOOKAHEAD) + { + // if the symbol cannot be resolved in the first HUFF_LOOKAHEAD bits, + // we know it lies somewhere between HUFF_LOOKAHEAD and 16 bits since jpeg imposes 16 bit + // limit, we can therefore look 16 bits ahead and try to resolve the symbol + // starting from 1+HUFF_LOOKAHEAD bits. + $symbol = ($stream).peek_bits::<16>() as i32; + // (Credits to Sean T. Barrett stb library for this optimization) + // maxcode is pre-shifted 16 bytes long so that it has (16-code_length) + // zeroes at the end hence we do not need to shift in the inner loop. + while code_length < 17{ + if $symbol < $table.maxcode[code_length as usize] { + break; + } + code_length += 1; + } + + if code_length == 17{ + // symbol could not be decoded. + // + // We may think, lets fake zeroes, noo + // panic, because Huffman codes are sensitive, probably everything + // after this will be corrupt, so no need to continue. + return Err(DecodeErrors::Format(format!("Bad Huffman Code 0x{:X}, corrupt JPEG",$symbol))) + } + + $symbol >>= (16-code_length); + ($symbol) = i32::from( + ($table).values + [(($symbol + ($table).offset[code_length as usize]) & 0xFF) as usize], + ); + } + // drop bits read + ($stream).drop_bits(code_length as u8); + }; +} + +/// A `BitStream` struct, a bit by bit reader with super powers +/// +pub(crate) struct BitStream { + /// A MSB type buffer that is used for some certain operations + pub buffer: u64, + /// A TOP aligned MSB type buffer that is used to accelerate some operations like + /// peek_bits and get_bits. + /// + /// By top aligned, I mean the top bit (63) represents the top bit in the buffer. + aligned_buffer: u64, + /// Tell us the bits left the two buffer + pub(crate) bits_left: u8, + /// Did we find a marker(RST/EOF) during decoding? + pub marker: Option, + + /// Progressive decoding + pub successive_high: u8, + pub successive_low: u8, + spec_start: u8, + spec_end: u8, + pub eob_run: i32, + pub overread_by: usize, + /// True if we have seen end of image marker. + /// Don't read anything after that. + pub seen_eoi: bool +} + +impl BitStream { + /// Create a new BitStream + pub(crate) const fn new() -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_high: 0, + successive_low: 0, + spec_start: 0, + spec_end: 0, + eob_run: 0, + overread_by: 0, + seen_eoi: false + } + } + + /// Create a new Bitstream for progressive decoding + #[allow(clippy::redundant_field_names)] + pub(crate) fn new_progressive(ah: u8, al: u8, spec_start: u8, spec_end: u8) -> BitStream { + BitStream { + buffer: 0, + aligned_buffer: 0, + bits_left: 0, + marker: None, + successive_high: ah, + successive_low: al, + spec_start: spec_start, + spec_end: spec_end, + eob_run: 0, + overread_by: 0, + seen_eoi: false + } + } + + /// Refill the bit buffer by (a maximum of) 32 bits + /// + /// # Arguments + /// - `reader`:`&mut BufReader`: A mutable reference to an underlying + /// File/Memory buffer containing a valid JPEG stream + /// + /// This function will only refill if `self.count` is less than 32 + #[inline(always)] // to many call sites? ( perf improvement by 4%) + fn refill(&mut self, reader: &mut ZReader) -> Result + where + T: ZByteReaderTrait + { + /// Macro version of a single byte refill. + /// Arguments + /// buffer-> our io buffer, because rust macros cannot get values from + /// the surrounding environment bits_left-> number of bits left + /// to full refill + macro_rules! refill { + ($buffer:expr,$byte:expr,$bits_left:expr) => { + // read a byte from the stream + $byte = u64::from(reader.read_u8()); + self.overread_by += usize::from(reader.eof()?); + // append to the buffer + // JPEG is a MSB type buffer so that means we append this + // to the lower end (0..8) of the buffer and push the rest bits above.. + $buffer = ($buffer << 8) | $byte; + // Increment bits left + $bits_left += 8; + // Check for special case of OxFF, to see if it's a stream or a marker + if $byte == 0xff { + // read next byte + let mut next_byte = u64::from(reader.read_u8()); + // Byte snuffing, if we encounter byte snuff, we skip the byte + if next_byte != 0x00 { + // skip that byte we read + while next_byte == 0xFF { + next_byte = u64::from(reader.read_u8()); + } + + if next_byte != 0x00 { + // Undo the byte append and return + $buffer >>= 8; + $bits_left -= 8; + + if $bits_left != 0 { + self.aligned_buffer = $buffer << (64 - $bits_left); + } + + self.marker = + Some(Marker::from_u8(next_byte as u8).ok_or_else(|| { + DecodeErrors::Format(format!( + "Unknown marker 0xFF{:X}", + next_byte + )) + })?); + return Ok(false); + } + } + } + }; + } + + // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits) + // If we have less than 32 bits we refill + if self.bits_left < 32 && self.marker.is_none() && !self.seen_eoi { + // we optimize for the case where we don't have 255 in the stream and have 4 bytes left + // as it is the common case + // + // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is + // guaranteed not to advance in case of failure (is this true), so + // we revert the read later on (if we have 255), if this fails, we use the normal + // byte at a time read + if let Ok(bytes) = reader.read_fixed_bytes_or_error::<4>() { + // we have 4 bytes to spare, read the 4 bytes into a temporary buffer + // create buffer + let msb_buf = u32::from_be_bytes(bytes); + // check if we have 0xff + if !has_byte(msb_buf, 255) { + self.bits_left += 32; + self.buffer <<= 32; + self.buffer |= u64::from(msb_buf); + self.aligned_buffer = self.buffer << (64 - self.bits_left); + return Ok(true); + } + + reader.rewind(4)?; + } + // This serves two reasons, + // 1: Make clippy shut up + // 2: Favour register reuse + let mut byte; + // 4 refills, if all succeed the stream should contain enough bits to decode a + // value + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + refill!(self.buffer, byte, self.bits_left); + // Construct an MSB buffer whose top bits are the bitstream we are currently holding. + self.aligned_buffer = self.buffer << (64 - self.bits_left); + } + return Ok(true); + } + /// Decode the DC coefficient in a MCU block. + /// + /// The decoded coefficient is written to `dc_prediction` + /// + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::unwrap_used + )] + #[inline(always)] + fn decode_dc( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, dc_prediction: &mut i32 + ) -> Result + where + T: ZByteReaderTrait + { + let (mut symbol, r); + + if self.bits_left < 32 { + self.refill(reader)?; + }; + // look a head HUFF_LOOKAHEAD bits into the bitstream + symbol = self.peek_bits::(); + symbol = dc_table.lookup[symbol as usize]; + + decode_huff!(self, symbol, dc_table); + + if symbol != 0 { + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + } + // Update DC prediction + *dc_prediction = dc_prediction.wrapping_add(symbol); + + return Ok(true); + } + + /// Decode a Minimum Code Unit(MCU) as quickly as possible + /// + /// # Arguments + /// - reader: The bitstream from where we read more bits. + /// - dc_table: The Huffman table used to decode the DC coefficient + /// - ac_table: The Huffman table used to decode AC values + /// - block: A memory region where we will write out the decoded values + /// - DC prediction: Last DC value for this component + /// + #[allow( + clippy::many_single_char_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + #[inline(never)] + pub fn decode_mcu_block( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, ac_table: &HuffmanTable, + qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32 + ) -> Result<(), DecodeErrors> + where + T: ZByteReaderTrait + { + // Get fast AC table as a reference before we enter the hot path + let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); + + let (mut symbol, mut r, mut fast_ac); + // Decode AC coefficients + let mut pos: usize = 1; + + // decode DC, dc prediction will contain the value + self.decode_dc(reader, dc_table, dc_prediction)?; + + // set dc to be the dc prediction. + block[0] = *dc_prediction * qt_table[0]; + + while pos < 64 { + self.refill(reader)?; + symbol = self.peek_bits::(); + fast_ac = ac_lookup[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fast_ac != 0 { + // FAST AC path + pos += ((fast_ac >> 4) & 15) as usize; // run + let t_pos = UN_ZIGZAG[min(pos, 63)] & 63; + + block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value + self.drop_bits((fast_ac & 15) as u8); + pos += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + pos += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + let t_pos = UN_ZIGZAG[pos & 63] & 63; + + block[t_pos] = symbol * qt_table[t_pos]; + + pos += 1; + } else if r != 15 { + return Ok(()); + } else { + pos += 16; + } + } + } + return Ok(()); + } + + /// Peek `look_ahead` bits ahead without discarding them from the buffer + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + const fn peek_bits(&self) -> i32 { + (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 + } + + /// Discard the next `N` bits without checking + #[inline] + fn drop_bits(&mut self, n: u8) { + self.bits_left = self.bits_left.saturating_sub(n); + self.aligned_buffer <<= n; + } + + /// Read `n_bits` from the buffer and discard them + #[inline(always)] + #[allow(clippy::cast_possible_truncation)] + fn get_bits(&mut self, n_bits: u8) -> i32 { + let mask = (1_u64 << n_bits) - 1; + + self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits)); + let bits = (self.aligned_buffer & mask) as i32; + self.bits_left = self.bits_left.wrapping_sub(n_bits); + bits + } + + /// Decode a DC block + #[allow(clippy::cast_possible_truncation)] + #[inline] + pub(crate) fn decode_prog_dc_first( + &mut self, reader: &mut ZReader, dc_table: &HuffmanTable, block: &mut i16, + dc_prediction: &mut i32 + ) -> Result<(), DecodeErrors> + where + T: ZByteReaderTrait + { + self.decode_dc(reader, dc_table, dc_prediction)?; + *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low); + return Ok(()); + } + #[inline] + pub(crate) fn decode_prog_dc_refine( + &mut self, reader: &mut ZReader, block: &mut i16 + ) -> Result<(), DecodeErrors> + where + T: ZByteReaderTrait + { + // refinement scan + if self.bits_left < 1 { + self.refill(reader)?; + } + + if self.get_bit() == 1 { + *block = block.wrapping_add(1 << self.successive_low); + } + + Ok(()) + } + + /// Get a single bit from the bitstream + fn get_bit(&mut self) -> u8 { + let k = (self.aligned_buffer >> 63) as u8; + // discard a bit + self.drop_bits(1); + return k; + } + pub(crate) fn decode_mcu_ac_first( + &mut self, reader: &mut ZReader, ac_table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZByteReaderTrait + { + let shift = self.successive_low; + let fast_ac = ac_table.ac_lookup.as_ref().unwrap(); + + let mut k = self.spec_start as usize; + let (mut symbol, mut r, mut fac); + + // EOB runs are handled in mcu_prog.rs + 'block: loop { + self.refill(reader)?; + + symbol = self.peek_bits::(); + fac = fast_ac[symbol as usize]; + symbol = ac_table.lookup[symbol as usize]; + + if fac != 0 { + // fast ac path + k += ((fac >> 4) & 15) as usize; // run + block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value + self.drop_bits((fac & 15) as u8); + k += 1; + } else { + decode_huff!(self, symbol, ac_table); + + r = symbol >> 4; + symbol &= 15; + + if symbol != 0 { + k += r as usize; + r = self.get_bits(symbol as u8); + symbol = huff_extend(r, symbol); + block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift); + k += 1; + } else { + if r != 15 { + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + self.eob_run -= 1; + break; + } + + k += 16; + } + } + + if k > self.spec_end as usize { + break 'block; + } + } + return Ok(true); + } + #[allow(clippy::too_many_lines, clippy::op_ref)] + pub(crate) fn decode_mcu_ac_refine( + &mut self, reader: &mut ZReader, table: &HuffmanTable, block: &mut [i16; 64] + ) -> Result + where + T: ZByteReaderTrait + { + let bit = (1 << self.successive_low) as i16; + + let mut k = self.spec_start; + let (mut symbol, mut r); + + if self.eob_run == 0 { + 'no_eob: loop { + // Decode a coefficient from the bit stream + self.refill(reader)?; + + symbol = self.peek_bits::(); + symbol = table.lookup[symbol as usize]; + + decode_huff!(self, symbol, table); + + r = symbol >> 4; + symbol &= 15; + + if symbol == 0 { + if r != 15 { + // EOB run is 2^r + bits + self.eob_run = 1 << r; + self.eob_run += self.get_bits(r as u8); + // EOB runs are handled by the eob logic + break 'no_eob; + } + } else { + if symbol != 1 { + return Err(DecodeErrors::HuffmanDecode( + "Bad Huffman code, corrupt JPEG?".to_string() + )); + } + // get sign bit + // We assume we have enough bits, which should be correct for sane images + // since we refill by 32 above + if self.get_bit() == 1 { + symbol = i32::from(bit); + } else { + symbol = i32::from(-bit); + } + } + + // Advance over already nonzero coefficients appending + // correction bits to the non-zeroes. + // A correction bit is 1 if the absolute value of the coefficient must be increased + + if k <= self.spec_end { + 'advance_nonzero: loop { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 { + if self.get_bit() == 1 && (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient += bit; + } else { + *coefficient -= bit; + } + } + + if self.bits_left < 1 { + self.refill(reader)?; + } + } else { + r -= 1; + + if r < 0 { + // reached target zero coefficient. + break 'advance_nonzero; + } + }; + + if k == self.spec_end { + break 'advance_nonzero; + } + + k += 1; + } + } + + if symbol != 0 { + let pos = UN_ZIGZAG[k as usize & 63]; + // output new non-zero coefficient. + block[pos & 63] = symbol as i16; + } + + k += 1; + + if k > self.spec_end { + break 'no_eob; + } + } + } + if self.eob_run > 0 { + // only run if block does not consists of purely zeroes + if &block[1..] != &[0; 63] { + self.refill(reader)?; + + while k <= self.spec_end { + let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; + + if *coefficient != 0 && self.get_bit() == 1 { + // check if we already modified it, if so do nothing, otherwise + // append the correction bit. + if (*coefficient & bit) == 0 { + if *coefficient >= 0 { + *coefficient = coefficient.wrapping_add(bit); + } else { + *coefficient = coefficient.wrapping_sub(bit); + } + } + } + if self.bits_left < 1 { + // refill at the last possible moment + self.refill(reader)?; + } + k += 1; + } + } + // count a block completed in EOB run + self.eob_run -= 1; + } + return Ok(true); + } + + pub fn update_progressive_params(&mut self, ah: u8, al: u8, spec_start: u8, spec_end: u8) { + self.successive_high = ah; + self.successive_low = al; + self.spec_start = spec_start; + self.spec_end = spec_end; + } + + /// Reset the stream if we have a restart marker + /// + /// Restart markers indicate drop those bits in the stream and zero out + /// everything + #[cold] + pub fn reset(&mut self) { + self.bits_left = 0; + self.marker = None; + self.buffer = 0; + self.aligned_buffer = 0; + self.eob_run = 0; + } +} + +/// Do the equivalent of JPEG HUFF_EXTEND +#[inline(always)] +fn huff_extend(x: i32, s: i32) -> i32 { + // if x> 31) & (((-1) << (s)) + 1)) +} + +const fn has_zero(v: u32) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0; +} + +const fn has_byte(b: u32, val: u8) -> bool { + // Retrieved from Stanford bithacks + // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + has_zero(b ^ ((!0_u32 / 255) * (val as u32))) +} diff --git a/third_party/zune-jpeg/src/color_convert.rs b/third_party/zune-jpeg/src/color_convert.rs new file mode 100644 index 0000000..1fca3b2 --- /dev/null +++ b/third_party/zune-jpeg/src/color_convert.rs @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow( + clippy::many_single_char_names, + clippy::similar_names, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::too_many_arguments, + clippy::doc_markdown +)] + +//! Color space conversion routines +//! +//! This files exposes functions to convert one colorspace to another in a jpeg +//! image +//! +//! Currently supported conversions are +//! +//! - `YCbCr` to `RGB,RGBA,GRAYSCALE,RGBX`. +//! +//! +//! Hey there, if your reading this it means you probably need something, so let me help you. +//! +//! There are 3 supported cpu extensions here. +//! 1. Scalar +//! 2. SSE +//! 3. AVX +//! +//! There are two types of the color convert functions +//! +//! 1. Acts on 16 pixels. +//! 2. Acts on 8 pixels. +//! +//! The reason for this is because when implementing the AVX part it occurred to me that we can actually +//! do better and process 2 MCU's if we change IDCT return type to be `i16's`, since a lot of +//! CPU's these days support AVX extensions, it becomes nice if we optimize for that path , +//! therefore AVX routines can process 16 pixels directly and SSE and Scalar just compensate. +//! +//! By compensating, I mean I wrote the 16 pixels version operating on the 8 pixel version twice. +//! +//! Therefore if your looking to optimize some routines, probably start there. + +pub use scalar::ycbcr_to_grayscale; +use zune_core::colorspace::ColorSpace; +use zune_core::options::DecoderOptions; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(feature = "x86")] +pub use crate::color_convert::avx::{ycbcr_to_rgb_avx2, ycbcr_to_rgba_avx2}; +use crate::decoder::ColorConvert16Ptr; + +mod avx; +mod scalar; +#[allow(unused_variables)] +pub fn choose_ycbcr_to_rgb_convert_func( + type_need: ColorSpace, options: &DecoderOptions +) -> Option { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + use zune_core::log::debug; + if options.use_avx2() { + debug!("Using AVX optimised color conversion functions"); + + // I believe avx2 means sse4 is also available + // match colorspace + match type_need { + ColorSpace::RGB => return Some(ycbcr_to_rgb_avx2), + ColorSpace::RGBA => return Some(ycbcr_to_rgba_avx2), + _ => () // fall through to scalar, which has more types + }; + } + } + // when there is no x86 or we haven't returned by here, resort to scalar + return match type_need { + ColorSpace::RGB => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + ColorSpace::RGBA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGRA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::), + ColorSpace::BGR => Some(scalar::ycbcr_to_rgb_inner_16_scalar::), + _ => None + }; +} diff --git a/third_party/zune-jpeg/src/color_convert/avx.rs b/third_party/zune-jpeg/src/color_convert/avx.rs new file mode 100644 index 0000000..5f828b5 --- /dev/null +++ b/third_party/zune-jpeg/src/color_convert/avx.rs @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! AVX color conversion routines +//! +//! Okay these codes are cool +//! +//! Herein lies super optimized codes to do color conversions. +//! +//! +//! 1. The YCbCr to RGB use integer approximations and not the floating point equivalent. +//! That means we may be +- 2 of pixels generated by libjpeg-turbo jpeg decoding +//! (also libjpeg uses routines like `Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G`) +//! +//! Firstly, we use integers (fun fact:there is no part of this code base where were dealing with +//! floating points.., fun fact: the first fun fact wasn't even fun.) +//! +//! Secondly ,we have cool clamping code, especially for rgba , where we don't need clamping and we +//! spend our time cursing that Intel decided permute instructions to work like 2 128 bit vectors(the compiler opitmizes +//! it out to something cool). +//! +//! There isn't a lot here (not as fun as bitstream ) but I hope you find what you're looking for. +//! +//! O and ~~subscribe to my youtube channel~~ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#![cfg(feature = "x86")] +#![allow( + clippy::wildcard_imports, + clippy::cast_possible_truncation, + clippy::too_many_arguments, + clippy::inline_always, + clippy::doc_markdown, + dead_code +)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +pub union YmmRegister { + // both are 32 when using std::mem::size_of + mm256: __m256i, + // for avx color conversion + array: [i16; 16] +} + +//-------------------------------------------------------------------------------------------------- +// AVX conversion routines +//-------------------------------------------------------------------------------------------------- + +/// +/// Convert YCBCR to RGB using AVX instructions +/// +/// # Note +///**IT IS THE RESPONSIBILITY OF THE CALLER TO CALL THIS IN CPUS SUPPORTING +/// AVX2 OTHERWISE THIS IS UB** +/// +/// *Peace* +/// +/// This library itself will ensure that it's never called in CPU's not +/// supporting AVX2 +/// +/// # Arguments +/// - `y`,`cb`,`cr`: A reference of 8 i32's +/// - `out`: The output array where we store our converted items +/// - `offset`: The position from 0 where we write these RGB values +#[inline(always)] +pub fn ycbcr_to_rgb_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // call this in another function to tell RUST to vectorize this + // storing + unsafe { + ycbcr_to_rgb_avx2_1(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +#[target_feature(enable = "avx")] +unsafe fn ycbcr_to_rgb_avx2_1( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + // Load output buffer + let tmp: &mut [u8; 48] = out + .get_mut(*offset..*offset + 48) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + + let (r, g, b) = ycbcr_to_rgb_baseline(y, cb, cr); + + let mut j = 0; + let mut i = 0; + while i < 48 { + tmp[i] = r.array[j] as u8; + + tmp[i + 1] = g.array[j] as u8; + tmp[i + 2] = b.array[j] as u8; + i += 3; + j += 1; + } + + *offset += 48; +} + +/// Baseline implementation of YCBCR to RGB for avx, +/// +/// It uses integer operations as opposed to floats, the approximation is +/// difficult for the eye to see, but this means that it may produce different +/// values with libjpeg_turbo. if accuracy is of utmost importance, use that. +/// +/// this function should be called for most implementations, including +/// - ycbcr->rgb +/// - ycbcr->rgba +/// - ycbcr->brga +/// - ycbcr->rgbx +#[inline] +#[target_feature(enable = "avx2")] +#[target_feature(enable = "avx")] +unsafe fn ycbcr_to_rgb_baseline( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (YmmRegister, YmmRegister, YmmRegister) { + // Load values into a register + // + // dst[127:0] := MEM[loaddr+127:loaddr] + // dst[255:128] := MEM[hiaddr+127:hiaddr] + let y_c = _mm256_loadu_si256(y.as_ptr().cast()); + + let cb_c = _mm256_loadu_si256(cb.as_ptr().cast()); + + let cr_c = _mm256_loadu_si256(cr.as_ptr().cast()); + + // AVX version of integer version in https://stackoverflow.com/questions/4041840/function-to-convert-ycbcr-to-rgb + + // Cb = Cb-128; + let cb_r = _mm256_sub_epi16(cb_c, _mm256_set1_epi16(128)); + + // cr = Cb -128; + let cr_r = _mm256_sub_epi16(cr_c, _mm256_set1_epi16(128)); + + // Calculate Y->R + // r = Y + 45 * Cr / 32 + // 45*cr + let r1 = _mm256_mullo_epi16(_mm256_set1_epi16(45), cr_r); + + // r1>>5 + let r2 = _mm256_srai_epi16::<5>(r1); + + //y+r2 + + let r = YmmRegister { + mm256: clamp_avx(_mm256_add_epi16(y_c, r2)) + }; + + // g = Y - (11 * Cb + 23 * Cr) / 32 ; + + // 11*cb + let g1 = _mm256_mullo_epi16(_mm256_set1_epi16(11), cb_r); + + // 23*cr + let g2 = _mm256_mullo_epi16(_mm256_set1_epi16(23), cr_r); + + //(11 + //(11 * Cb + 23 * Cr) + let g3 = _mm256_add_epi16(g1, g2); + + // (11 * Cb + 23 * Cr) / 32 + let g4 = _mm256_srai_epi16::<5>(g3); + + // Y - (11 * Cb + 23 * Cr) / 32 ; + let g = YmmRegister { + mm256: clamp_avx(_mm256_sub_epi16(y_c, g4)) + }; + + // b = Y + 113 * Cb / 64 + // 113 * cb + let b1 = _mm256_mullo_epi16(_mm256_set1_epi16(113), cb_r); + + //113 * Cb / 64 + let b2 = _mm256_srai_epi16::<6>(b1); + + // b = Y + 113 * Cb / 64 ; + let b = YmmRegister { + mm256: clamp_avx(_mm256_add_epi16(b2, y_c)) + }; + + return (r, g, b); +} + +#[inline] +#[target_feature(enable = "avx2")] +/// A baseline implementation of YCbCr to RGB conversion which does not carry +/// out clamping +/// +/// This is used by the `ycbcr_to_rgba_avx` and `ycbcr_to_rgbx` conversion +/// routines +unsafe fn ycbcr_to_rgb_baseline_no_clamp( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16] +) -> (__m256i, __m256i, __m256i) { + // Load values into a register + // + let y_c = _mm256_loadu_si256(y.as_ptr().cast()); + + let cb_c = _mm256_loadu_si256(cb.as_ptr().cast()); + + let cr_c = _mm256_loadu_si256(cr.as_ptr().cast()); + + // AVX version of integer version in https://stackoverflow.com/questions/4041840/function-to-convert-ycbcr-to-rgb + + // Cb = Cb-128; + let cb_r = _mm256_sub_epi16(cb_c, _mm256_set1_epi16(128)); + + // cr = Cb -128; + let cr_r = _mm256_sub_epi16(cr_c, _mm256_set1_epi16(128)); + + // Calculate Y->R + // r = Y + 45 * Cr / 32 + // 45*cr + let r1 = _mm256_mullo_epi16(_mm256_set1_epi16(45), cr_r); + + // r1>>5 + let r2 = _mm256_srai_epi16::<5>(r1); + + //y+r2 + + let r = _mm256_add_epi16(y_c, r2); + + // g = Y - (11 * Cb + 23 * Cr) / 32 ; + + // 11*cb + let g1 = _mm256_mullo_epi16(_mm256_set1_epi16(11), cb_r); + + // 23*cr + let g2 = _mm256_mullo_epi16(_mm256_set1_epi16(23), cr_r); + + //(11 + //(11 * Cb + 23 * Cr) + let g3 = _mm256_add_epi16(g1, g2); + + // (11 * Cb + 23 * Cr) / 32 + let g4 = _mm256_srai_epi16::<5>(g3); + + // Y - (11 * Cb + 23 * Cr) / 32 ; + let g = _mm256_sub_epi16(y_c, g4); + + // b = Y + 113 * Cb / 64 + // 113 * cb + let b1 = _mm256_mullo_epi16(_mm256_set1_epi16(113), cb_r); + + //113 * Cb / 64 + let b2 = _mm256_srai_epi16::<6>(b1); + + // b = Y + 113 * Cb / 64 ; + let b = _mm256_add_epi16(b2, y_c); + + return (r, g, b); +} + +#[inline(always)] +pub fn ycbcr_to_rgba_avx2( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], out: &mut [u8], offset: &mut usize +) { + unsafe { + ycbcr_to_rgba_unsafe(y, cb, cr, out, offset); + } +} + +#[inline] +#[target_feature(enable = "avx2")] +#[rustfmt::skip] +unsafe fn ycbcr_to_rgba_unsafe( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], + out: &mut [u8], + offset: &mut usize, +) +{ + // check if we have enough space to write. + let tmp:& mut [u8; 64] = out.get_mut(*offset..*offset + 64).expect("Slice to small cannot write").try_into().unwrap(); + + let (r, g, b) = ycbcr_to_rgb_baseline_no_clamp(y, cb, cr); + + // set alpha channel to 255 for opaque + + // And no these comments were not from me pressing the keyboard + + // Pack the integers into u8's using signed saturation. + let c = _mm256_packus_epi16(r, g); //aaaaa_bbbbb_aaaaa_bbbbbb + let d = _mm256_packus_epi16(b, _mm256_set1_epi16(255)); // cccccc_dddddd_ccccccc_ddddd + // transpose_u16 and interleave channels + let e = _mm256_unpacklo_epi8(c, d); //ab_ab_ab_ab_ab_ab_ab_ab + let f = _mm256_unpackhi_epi8(c, d); //cd_cd_cd_cd_cd_cd_cd_cd + // final transpose_u16 + let g = _mm256_unpacklo_epi8(e, f); //abcd_abcd_abcd_abcd_abcd + let h = _mm256_unpackhi_epi8(e, f); + + + // undo packus shuffling... + let i = _mm256_permute2x128_si256::<{ shuffle(3, 2, 1, 0) }>(g, h); + + let j = _mm256_permute2x128_si256::<{ shuffle(1, 2, 3, 0) }>(g, h); + + let k = _mm256_permute2x128_si256::<{ shuffle(3, 2, 0, 1) }>(g, h); + + let l = _mm256_permute2x128_si256::<{ shuffle(0, 3, 2, 1) }>(g, h); + + let m = _mm256_blend_epi32::<0b1111_0000>(i, j); + + let n = _mm256_blend_epi32::<0b1111_0000>(k, l); + + + // Store + // Use streaming instructions to prevent polluting the cache? + _mm256_storeu_si256(tmp.as_mut_ptr().cast(), m); + + _mm256_storeu_si256(tmp[32..].as_mut_ptr().cast(), n); + + *offset += 64; +} + +/// Clamp values between 0 and 255 +/// +/// This function clamps all values in `reg` to be between 0 and 255 +///( the accepted values for RGB) +#[inline] +#[target_feature(enable = "avx2")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn clamp_avx(reg: __m256i) -> __m256i { + // the lowest value + let min_s = _mm256_set1_epi16(0); + + // Highest value + let max_s = _mm256_set1_epi16(255); + + let max_v = _mm256_max_epi16(reg, min_s); //max(a,0) + let min_v = _mm256_min_epi16(max_v, max_s); //min(max(a,0),255) + return min_v; +} + +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} diff --git a/third_party/zune-jpeg/src/color_convert/scalar.rs b/third_party/zune-jpeg/src/color_convert/scalar.rs new file mode 100644 index 0000000..f217f30 --- /dev/null +++ b/third_party/zune-jpeg/src/color_convert/scalar.rs @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use core::convert::TryInto; + +/// Limit values to 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, dead_code)] +fn clamp(a: i16) -> u8 { + a.clamp(0, 255) as u8 +} + +/// YCbCr to RGBA color conversion + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgba_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 64 elements for Rust to see we won't go out of bounds. + let opt: &mut [u8; 64] = output_position + .get_mut(0..64) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + for ((y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(4)) + { + let cr = cr - 128; + let cb = cb - 128; + + let r = y + ((45_i16.wrapping_mul(cr)) >> 5); + let g = y - ((11_i16.wrapping_mul(cb) + 23_i16.wrapping_mul(cr)) >> 5); + let b = y + ((113_i16.wrapping_mul(cb)) >> 6); + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + out[3] = 255; + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + out[3] = 255; + } + } + *pos += 64; +} + +/// Convert YCbCr to RGB/BGR +/// +/// Converts to RGB if const BGRA is false +/// +/// Converts to BGR if const BGRA is true +pub fn ycbcr_to_rgb_inner_16_scalar( + y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize +) { + let (_, output_position) = output.split_at_mut(*pos); + + // Convert into a slice with 48 elements + let opt: &mut [u8; 48] = output_position + .get_mut(0..48) + .expect("Slice to small cannot write") + .try_into() + .unwrap(); + + for ((y, (cb, cr)), out) in y + .iter() + .zip(cb.iter().zip(cr.iter())) + .zip(opt.chunks_exact_mut(3)) + { + let cr = cr - 128; + let cb = cb - 128; + + let r = y + ((45_i16.wrapping_mul(cr)) >> 5); + let g = y - ((11_i16.wrapping_mul(cb) + 23_i16.wrapping_mul(cr)) >> 5); + let b = y + ((113_i16.wrapping_mul(cb)) >> 6); + + if BGRA { + out[0] = clamp(b); + out[1] = clamp(g); + out[2] = clamp(r); + } else { + out[0] = clamp(r); + out[1] = clamp(g); + out[2] = clamp(b); + } + } + + // Increment pos + *pos += 48; +} + +pub fn ycbcr_to_grayscale(y: &[i16], width: usize, padded_width: usize, output: &mut [u8]) { + for (y_in, out) in y + .chunks_exact(padded_width) + .zip(output.chunks_exact_mut(width)) + { + for (y, out) in y_in.iter().zip(out.iter_mut()) { + *out = *y as u8; + } + } +} diff --git a/third_party/zune-jpeg/src/components.rs b/third_party/zune-jpeg/src/components.rs new file mode 100644 index 0000000..467c33a --- /dev/null +++ b/third_party/zune-jpeg/src/components.rs @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This module exports a single struct to store information about +//! JPEG image components +//! +//! The data is extracted from a SOF header. + +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::log::trace; + +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::upsampler::upsample_no_op; + +/// Represents an up-sampler function, this function will be called to upsample +/// a down-sampled image + +pub type UpSampler = fn( + input: &[i16], + in_near: &[i16], + in_far: &[i16], + scratch_space: &mut [i16], + output: &mut [i16] +); + +/// Component Data from start of frame +#[derive(Clone)] +pub(crate) struct Components { + /// The type of component that has the metadata below, can be Y,Cb or Cr + pub component_id: ComponentID, + /// Sub-sampling ratio of this component in the x-plane + pub vertical_sample: usize, + /// Sub-sampling ratio of this component in the y-plane + pub horizontal_sample: usize, + /// DC huffman table position + pub dc_huff_table: usize, + /// AC huffman table position for this element. + pub ac_huff_table: usize, + /// Quantization table number + pub quantization_table_number: u8, + /// Specifies quantization table to use with this component + pub quantization_table: [i32; 64], + /// dc prediction for the component + pub dc_pred: i32, + /// An up-sampling function, can be basic or SSE, depending + /// on the platform + pub up_sampler: UpSampler, + /// How pixels do we need to go to get to the next line? + pub width_stride: usize, + /// Component ID for progressive + pub id: u8, + /// Whether we need to decode this image component. + pub needed: bool, + /// Upsample scanline + pub raw_coeff: Vec, + /// Upsample destination, stores a scanline worth of sub sampled data + pub upsample_dest: Vec, + /// previous row, used to handle MCU boundaries + pub row_up: Vec, + /// current row, used to handle MCU boundaries again + pub row: Vec, + pub first_row_upsample_dest: Vec, + pub idct_pos: usize, + pub x: usize, + pub w2: usize, + pub y: usize, + pub sample_ratio: SampleRatios, + // a very annoying bug + pub fix_an_annoying_bug: usize +} + +impl Components { + /// Create a new instance from three bytes from the start of frame + #[inline] + pub fn from(a: [u8; 3], pos: u8) -> Result { + // it's a unique identifier. + // doesn't have to be ascending + // see tests/inputs/huge_sof_number + // + // For such cases, use the position of the component + // to determine width + + let id = match pos { + 0 => ComponentID::Y, + 1 => ComponentID::Cb, + 2 => ComponentID::Cr, + 3 => ComponentID::Q, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown component id found,{pos}, expected value between 1 and 4" + ))) + } + }; + + let horizontal_sample = (a[1] >> 4) as usize; + let vertical_sample = (a[1] & 0x0f) as usize; + let quantization_table_number = a[2]; + // confirm quantization number is between 0 and MAX_COMPONENTS + if usize::from(quantization_table_number) >= MAX_COMPONENTS { + return Err(DecodeErrors::Format(format!( + "Too large quantization number :{quantization_table_number}, expected value between 0 and {MAX_COMPONENTS}" + ))); + } + // check that upsampling ratios are powers of two + // if these fail, it's probably a corrupt image. + if !horizontal_sample.is_power_of_two() { + return Err(DecodeErrors::Format(format!( + "Horizontal sample is not a power of two({horizontal_sample}) cannot decode" + ))); + } + + if !vertical_sample.is_power_of_two() { + return Err(DecodeErrors::Format(format!( + "Vertical sub-sample is not power of two({vertical_sample}) cannot decode" + ))); + } + + trace!( + "Component ID:{:?} \tHS:{} VS:{} QT:{}", + id, + horizontal_sample, + vertical_sample, + quantization_table_number + ); + + Ok(Components { + component_id: id, + vertical_sample, + horizontal_sample, + quantization_table_number, + first_row_upsample_dest: vec![], + // These two will be set with sof marker + dc_huff_table: 0, + ac_huff_table: 0, + quantization_table: [0; 64], + dc_pred: 0, + up_sampler: upsample_no_op, + // set later + width_stride: horizontal_sample, + id: a[0], + needed: true, + raw_coeff: vec![], + upsample_dest: vec![], + row_up: vec![], + row: vec![], + idct_pos: 0, + x: 0, + y: 0, + w2: 0, + sample_ratio: SampleRatios::None, + fix_an_annoying_bug: 1 + }) + } + /// Setup space for upsampling + /// + /// During upsample, we need a reference of the last row so that upsampling can + /// proceed correctly, + /// so we store the last line of every scanline and use it for the next upsampling procedure + /// to store this, but since we don't need it for 1v1 upsampling, + /// we only call this for routines that need upsampling + /// + /// # Requirements + /// - width stride of this element is set for the component. + pub fn setup_upsample_scanline(&mut self) { + self.row = vec![0; self.width_stride * self.vertical_sample]; + self.row_up = vec![0; self.width_stride * self.vertical_sample]; + self.first_row_upsample_dest = + vec![128; self.vertical_sample * self.width_stride * self.sample_ratio.sample()]; + self.upsample_dest = + vec![0; self.width_stride * self.sample_ratio.sample() * self.fix_an_annoying_bug * 8]; + } +} + +/// Component ID's +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum ComponentID { + /// Luminance channel + Y, + /// Blue chrominance + Cb, + /// Red chrominance + Cr, + /// Q or fourth component + Q +} + +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum SampleRatios { + HV, + V, + H, + None +} + +impl SampleRatios { + pub fn sample(self) -> usize { + match self { + SampleRatios::HV => 4, + SampleRatios::V | SampleRatios::H => 2, + SampleRatios::None => 1 + } + } +} diff --git a/third_party/zune-jpeg/src/decoder.rs b/third_party/zune-jpeg/src/decoder.rs new file mode 100644 index 0000000..dab33b6 --- /dev/null +++ b/third_party/zune-jpeg/src/decoder.rs @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Main image logic. +#![allow(clippy::doc_markdown)] + +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{error, trace, warn}; +use zune_core::options::DecoderOptions; + +use crate::color_convert::choose_ycbcr_to_rgb_convert_func; +use crate::components::{Components, SampleRatios}; +use crate::errors::{DecodeErrors, UnsupportedSchemes}; +use crate::headers::{ + parse_app1, parse_app14, parse_app2, parse_dqt, parse_huffman, parse_sos, parse_start_of_frame +}; +use crate::huffman::HuffmanTable; +use crate::idct::choose_idct_func; +use crate::marker::Marker; +use crate::misc::SOFMarkers; +use crate::upsampler::{ + choose_horizontal_samp_function, choose_hv_samp_function, choose_v_samp_function, + upsample_no_op +}; + +/// Maximum components +pub(crate) const MAX_COMPONENTS: usize = 4; + +/// Maximum image dimensions supported. +pub(crate) const MAX_DIMENSIONS: usize = 1 << 27; + +/// Color conversion function that can convert YCbCr colorspace to RGB(A/X) for +/// 16 values +/// +/// The following are guarantees to the following functions +/// +/// 1. The `&[i16]` slices passed contain 16 items +/// +/// 2. The slices passed are in the following order +/// `y,cb,cr` +/// +/// 3. `&mut [u8]` is zero initialized +/// +/// 4. `&mut usize` points to the position in the array where new values should +/// be used +/// +/// The pointer should +/// 1. Carry out color conversion +/// 2. Update `&mut usize` with the new position + +pub type ColorConvert16Ptr = fn(&[i16; 16], &[i16; 16], &[i16; 16], &mut [u8], &mut usize); + +/// IDCT function prototype +/// +/// This encapsulates a dequantize and IDCT function which will carry out the +/// following functions +/// +/// Multiply each 64 element block of `&mut [i16]` with `&Aligned32<[i32;64]>` +/// Carry out IDCT (type 3 dct) on ach block of 64 i16's +pub type IDCTPtr = fn(&mut [i32; 64], &mut [i16], usize); + +/// An encapsulation of an ICC chunk +pub(crate) struct ICCChunk { + pub(crate) seq_no: u8, + pub(crate) num_markers: u8, + pub(crate) data: Vec +} + +/// A JPEG Decoder Instance. +#[allow(clippy::upper_case_acronyms, clippy::struct_excessive_bools)] +pub struct JpegDecoder { + /// Struct to hold image information from SOI + pub(crate) info: ImageInfo, + /// Quantization tables, will be set to none and the tables will + /// be moved to `components` field + pub(crate) qt_tables: [Option<[i32; 64]>; MAX_COMPONENTS], + /// DC Huffman Tables with a maximum of 4 tables for each component + pub(crate) dc_huffman_tables: [Option; MAX_COMPONENTS], + /// AC Huffman Tables with a maximum of 4 tables for each component + pub(crate) ac_huffman_tables: [Option; MAX_COMPONENTS], + /// Image components, holds information like DC prediction and quantization + /// tables of a component + pub(crate) components: Vec, + /// maximum horizontal component of all channels in the image + pub(crate) h_max: usize, + // maximum vertical component of all channels in the image + pub(crate) v_max: usize, + /// mcu's width (interleaved scans) + pub(crate) mcu_width: usize, + /// MCU height(interleaved scans + pub(crate) mcu_height: usize, + /// Number of MCU's in the x plane + pub(crate) mcu_x: usize, + /// Number of MCU's in the y plane + pub(crate) mcu_y: usize, + /// Is the image interleaved? + pub(crate) is_interleaved: bool, + pub(crate) sub_sample_ratio: SampleRatios, + /// Image input colorspace, should be YCbCr for a sane image, might be + /// grayscale too + pub(crate) input_colorspace: ColorSpace, + // Progressive image details + /// Is the image progressive? + pub(crate) is_progressive: bool, + + /// Start of spectral scan + pub(crate) spec_start: u8, + /// End of spectral scan + pub(crate) spec_end: u8, + /// Successive approximation bit position high + pub(crate) succ_high: u8, + /// Successive approximation bit position low + pub(crate) succ_low: u8, + /// Number of components. + pub(crate) num_scans: u8, + // Function pointers, for pointy stuff. + /// Dequantize and idct function + // This is determined at runtime which function to run, statically it's + // initialized to a platform independent one and during initialization + // of this struct, we check if we can switch to a faster one which + // depend on certain CPU extensions. + pub(crate) idct_func: IDCTPtr, + // Color convert function which acts on 16 YCbCr values + pub(crate) color_convert_16: ColorConvert16Ptr, + pub(crate) z_order: [usize; MAX_COMPONENTS], + /// restart markers + pub(crate) restart_interval: usize, + pub(crate) todo: usize, + // decoder options + pub(crate) options: DecoderOptions, + // byte-stream + pub(crate) stream: ZReader, + // Indicate whether headers have been decoded + pub(crate) headers_decoded: bool, + pub(crate) seen_sof: bool, + // exif data, lifted from app2 + pub(crate) exif_data: Option>, + + pub(crate) icc_data: Vec, + pub(crate) is_mjpeg: bool, + pub(crate) coeff: usize // Solves some weird bug :) +} + +impl JpegDecoder +where + T: ZByteReaderTrait +{ + #[allow(clippy::redundant_field_names)] + fn default(options: DecoderOptions, buffer: T) -> Self { + let color_convert = choose_ycbcr_to_rgb_convert_func(ColorSpace::RGB, &options).unwrap(); + JpegDecoder { + info: ImageInfo::default(), + qt_tables: [None, None, None, None], + dc_huffman_tables: [None, None, None, None], + ac_huffman_tables: [None, None, None, None], + components: vec![], + // Interleaved information + h_max: 1, + v_max: 1, + mcu_height: 0, + mcu_width: 0, + mcu_x: 0, + mcu_y: 0, + is_interleaved: false, + sub_sample_ratio: SampleRatios::None, + is_progressive: false, + spec_start: 0, + spec_end: 0, + succ_high: 0, + succ_low: 0, + num_scans: 0, + idct_func: choose_idct_func(&options), + color_convert_16: color_convert, + input_colorspace: ColorSpace::YCbCr, + z_order: [0; MAX_COMPONENTS], + restart_interval: 0, + todo: 0x7fff_ffff, + options: options, + stream: ZReader::new(buffer), + headers_decoded: false, + seen_sof: false, + exif_data: None, + icc_data: vec![], + is_mjpeg: false, + coeff: 1 + } + } + /// Decode a buffer already in memory + /// + /// The buffer should be a valid jpeg file, perhaps created by the command + /// `std:::fs::read()` or a JPEG file downloaded from the internet. + /// + /// # Errors + /// See DecodeErrors for an explanation + pub fn decode(&mut self) -> Result, DecodeErrors> { + self.decode_headers()?; + let size = self.output_buffer_size().unwrap(); + let mut out = vec![0; size]; + self.decode_into(&mut out)?; + Ok(out) + } + + /// Create a new Decoder instance + /// + /// # Arguments + /// - `stream`: The raw bytes of a jpeg file. + #[must_use] + #[allow(clippy::new_without_default)] + pub fn new(stream: T) -> JpegDecoder { + JpegDecoder::default(DecoderOptions::default(), stream) + } + + /// Returns the image information + /// + /// This **must** be called after a subsequent call to [`decode`] or [`decode_headers`] + /// it will return `None` + /// + /// # Returns + /// - `Some(info)`: Image information,width, height, number of components + /// - None: Indicates image headers haven't been decoded + /// + /// [`decode`]: JpegDecoder::decode + /// [`decode_headers`]: JpegDecoder::decode_headers + #[must_use] + pub fn info(&self) -> Option { + // we check for fails to that call by comparing what we have to the default, if + // it's default we assume that the caller failed to uphold the + // guarantees. We can be sure that an image cannot be the default since + // its a hard panic in-case width or height are set to zero. + if !self.headers_decoded { + return None; + } + + return Some(self.info.clone()); + } + + /// Return the number of bytes required to hold a decoded image frame + /// decoded using the given input transformations + /// + /// # Returns + /// - `Some(usize)`: Minimum size for a buffer needed to decode the image + /// - `None`: Indicates the image was not decoded, or image dimensions would overflow a usize + /// + #[must_use] + pub fn output_buffer_size(&self) -> Option { + return if self.headers_decoded { + Some( + usize::from(self.width()) + .checked_mul(usize::from(self.height()))? + .checked_mul(self.options.jpeg_get_out_colorspace().num_components())? + ) + } else { + None + }; + } + + /// Get an immutable reference to the decoder options + /// for the decoder instance + /// + /// This can be used to modify options before actual decoding + /// but after initial creation + /// + /// # Example + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// + /// let mut decoder = JpegDecoder::new(ZCursor::new(&[])); + /// // get current options + /// let mut options = decoder.options(); + /// // modify it + /// let new_options = options.set_max_width(10); + /// // set it back + /// decoder.set_options(new_options); + /// + /// ``` + #[must_use] + pub const fn options(&self) -> &DecoderOptions { + &self.options + } + /// Return the input colorspace of the image + /// + /// This indicates the colorspace that is present in + /// the image, but this may be different to the colorspace that + /// the output will be transformed to + /// + /// # Returns + /// -`Some(Colorspace)`: Input colorspace + /// - None : Indicates the headers weren't decoded + #[must_use] + pub fn input_colorspace(&self) -> Option { + return if self.headers_decoded { Some(self.input_colorspace) } else { None }; + } + /// Set decoder options + /// + /// This can be used to set new options even after initialization + /// but before decoding. + /// + /// This does not bear any significance after decoding an image + /// + /// # Arguments + /// - `options`: New decoder options + /// + /// # Example + /// Set maximum jpeg progressive passes to be 4 + /// + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// let mut decoder =JpegDecoder::new(ZCursor::new(&[])); + /// // this works also because DecoderOptions implements `Copy` + /// let options = decoder.options().jpeg_set_max_scans(4); + /// // set the new options + /// decoder.set_options(options); + /// // now decode + /// decoder.decode().unwrap(); + /// ``` + pub fn set_options(&mut self, options: DecoderOptions) { + self.options = options; + } + /// Decode Decoder headers + /// + /// This routine takes care of parsing supported headers from a Decoder + /// image + /// + /// # Supported Headers + /// - APP(0) + /// - SOF(O) + /// - DQT -> Quantization tables + /// - DHT -> Huffman tables + /// - SOS -> Start of Scan + /// # Unsupported Headers + /// - SOF(n) -> Decoder images which are not baseline/progressive + /// - DAC -> Images using Arithmetic tables + /// - JPG(n) + fn decode_headers_internal(&mut self) -> Result<(), DecodeErrors> { + if self.headers_decoded { + trace!("Headers decoded!"); + return Ok(()); + } + // match output colorspace here + // we know this will only be called once per image + // so makes sense + // We only care for ycbcr to rgb/rgba here + // in case one is using another colorspace. + // May god help you + let out_colorspace = self.options.jpeg_get_out_colorspace(); + + if matches!( + out_colorspace, + ColorSpace::BGR | ColorSpace::BGRA | ColorSpace::RGB | ColorSpace::RGBA + ) { + self.color_convert_16 = choose_ycbcr_to_rgb_convert_func( + self.options.jpeg_get_out_colorspace(), + &self.options + ) + .unwrap(); + } + // First two bytes should be jpeg soi marker + let magic_bytes = self.stream.get_u16_be_err()?; + + let mut last_byte = 0; + let mut bytes_before_marker = 0; + + if magic_bytes != 0xffd8 { + return Err(DecodeErrors::IllegalMagicBytes(magic_bytes)); + } + + loop { + // read a byte + let mut m = self.stream.read_u8_err()?; + + // AND OF COURSE some images will have fill bytes in their marker + // bitstreams because why not. + // + // I am disappointed as a man. + if (m == 0xFF || m == 0) && last_byte == 0xFF { + // This handles the edge case where + // images have markers with fill bytes(0xFF) + // or byte stuffing (0) + // I.e 0xFF 0xFF 0xDA + // and + // 0xFF 0 0xDA + // It should ignore those fill bytes and take 0xDA + // I don't know why such images exist + // but they do. + // so this is for you (with love) + while m == 0xFF || m == 0x0 { + last_byte = m; + m = self.stream.read_u8_err()?; + } + } + // Last byte should be 0xFF to confirm existence of a marker since markers look + // like OxFF(some marker data) + if last_byte == 0xFF { + let marker = Marker::from_u8(m); + if let Some(n) = marker { + if bytes_before_marker > 3 { + if self.options.strict_mode() + /*No reason to use this*/ + { + return Err(DecodeErrors::FormatStatic( + "[strict-mode]: Extra bytes between headers" + )); + } + + error!( + "Extra bytes {} before marker 0xFF{:X}", + bytes_before_marker - 3, + m + ); + } + + bytes_before_marker = 0; + + self.parse_marker_inner(n)?; + + if n == Marker::SOS { + self.headers_decoded = true; + trace!("Input colorspace {:?}", self.input_colorspace); + return Ok(()); + } + } else { + bytes_before_marker = 0; + + warn!("Marker 0xFF{:X} not known", m); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length : {length}" + ))); + } + + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize)?; + } + } + last_byte = m; + bytes_before_marker += 1; + } + } + #[allow(clippy::too_many_lines)] + pub(crate) fn parse_marker_inner(&mut self, m: Marker) -> Result<(), DecodeErrors> { + match m { + Marker::SOF(0..=2) => { + let marker = { + // choose marker + if m == Marker::SOF(0) || m == Marker::SOF(1) { + SOFMarkers::BaselineDct + } else { + self.is_progressive = true; + SOFMarkers::ProgressiveDctHuffman + } + }; + + trace!("Image encoding scheme =`{:?}`", marker); + // get components + parse_start_of_frame(marker, self)?; + } + // Start of Frame Segments not supported + Marker::SOF(v) => { + let feature = UnsupportedSchemes::from_int(v); + + if let Some(feature) = feature { + return Err(DecodeErrors::Unsupported(feature)); + } + + return Err(DecodeErrors::Format("Unsupported image format".to_string())); + } + //APP(0) segment + Marker::APP(0) => { + let mut length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + // skip for now + if length > 5 { + let mut buffer = [0u8; 5]; + self.stream.read_exact_bytes(&mut buffer)?; + if &buffer == b"AVI1\0" { + self.is_mjpeg = true; + } + length -= 5; + } + + self.stream.skip(length.saturating_sub(2) as usize)?; + + //parse_app(buf, m, &mut self.info)?; + } + Marker::APP(1) => { + parse_app1(self)?; + } + + Marker::APP(2) => { + parse_app2(self)?; + } + // Quantization tables + Marker::DQT => { + parse_dqt(self)?; + } + // Huffman tables + Marker::DHT => { + parse_huffman(self)?; + } + // Start of Scan Data + Marker::SOS => { + parse_sos(self)?; + + // break after reading the start of scan. + // what follows is the image data + return Ok(()); + } + Marker::EOI => return Err(DecodeErrors::FormatStatic("Premature End of image")), + + Marker::DAC | Marker::DNL => { + return Err(DecodeErrors::Format(format!( + "Parsing of the following header `{m:?}` is not supported,\ + cannot continue" + ))); + } + Marker::DRI => { + trace!("DRI marker present"); + + if self.stream.get_u16_be_err()? != 4 { + return Err(DecodeErrors::Format( + "Bad DRI length, Corrupt JPEG".to_string() + )); + } + + self.restart_interval = usize::from(self.stream.get_u16_be_err()?); + self.todo = self.restart_interval; + } + Marker::APP(14) => { + parse_app14(self)?; + } + _ => { + warn!( + "Capabilities for processing marker \"{:?}\" not implemented", + m + ); + + let length = self.stream.get_u16_be_err()?; + + if length < 2 { + return Err(DecodeErrors::Format(format!( + "Found a marker with invalid length:{length}\n" + ))); + } + warn!("Skipping {} bytes", length - 2); + self.stream.skip((length - 2) as usize)?; + } + } + Ok(()) + } + /// Get the embedded ICC profile if it exists + /// and is correct + /// + /// One needs not to decode the whole image to extract this, + /// calling [`decode_headers`] for an image with an ICC profile + /// allows you to decode this + /// + /// # Returns + /// - `Some(Vec)`: The raw ICC profile of the image + /// - `None`: May indicate an error in the ICC profile , non-existence of + /// an ICC profile, or that the headers weren't decoded. + /// + /// [`decode_headers`]:Self::decode_headers + #[must_use] + pub fn icc_profile(&self) -> Option> { + let mut marker_present: [Option<&ICCChunk>; 256] = [None; 256]; + + if !self.headers_decoded { + return None; + } + let num_markers = self.icc_data.len(); + + if num_markers == 0 || num_markers >= 255 { + return None; + } + // check validity + for chunk in &self.icc_data { + if usize::from(chunk.num_markers) != num_markers { + // all the lengths must match + return None; + } + if chunk.seq_no == 0 { + warn!("Zero sequence number in ICC, corrupt ICC chunk"); + return None; + } + if marker_present[usize::from(chunk.seq_no)].is_some() { + // duplicate seq_no + warn!("Duplicate sequence number in ICC, corrupt chunk"); + return None; + } + + marker_present[usize::from(chunk.seq_no)] = Some(chunk); + } + let mut data = Vec::with_capacity(1000); + // assemble the data now + for chunk in marker_present.get(1..=num_markers).unwrap() { + if let Some(ch) = chunk { + data.extend_from_slice(&ch.data); + } else { + warn!("Missing icc sequence number, corrupt ICC chunk "); + return None; + } + } + + Some(data) + } + /// Return the exif data for the file + /// + /// This returns the raw exif data starting at the + /// TIFF header + /// + /// # Returns + /// -`Some(data)`: The raw exif data, if present in the image + /// - None: May indicate the following + /// + /// 1. The image doesn't have exif data + /// 2. The image headers haven't been decoded + #[must_use] + pub fn exif(&self) -> Option<&Vec> { + return self.exif_data.as_ref(); + } + /// Get the output colorspace the image pixels will be decoded into + /// + /// + /// # Note. + /// This field can only be regarded after decoding headers, + /// as markers such as Adobe APP14 may dictate different colorspaces + /// than requested. + /// + /// Calling `decode_headers` is sufficient to know what colorspace the + /// output is, if this is called after `decode` it indicates the colorspace + /// the output is currently in + /// + /// Additionally not all input->output colorspace mappings are supported + /// but all input colorspaces can map to RGB colorspace, so that's a safe bet + /// if one is handling image formats + /// + ///# Returns + /// - `Some(Colorspace)`: If headers have been decoded, the colorspace the + ///output array will be in + ///- `None + #[must_use] + pub fn output_colorspace(&self) -> Option { + return if self.headers_decoded { + Some(self.options.jpeg_get_out_colorspace()) + } else { + None + }; + } + + /// Decode into a pre-allocated buffer + /// + /// It is an error if the buffer size is smaller than + /// [`output_buffer_size()`](Self::output_buffer_size) + /// + /// If the buffer is bigger than expected, we ignore the end padding bytes + /// + /// # Example + /// + /// - Read headers and then alloc a buffer big enough to hold the image + /// + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::JpegDecoder; + /// let mut decoder = JpegDecoder::new(ZCursor::new(&[])); + /// // before we get output, we must decode the headers to get width + /// // height, and input colorspace + /// decoder.decode_headers().unwrap(); + /// + /// let mut out = vec![0;decoder.output_buffer_size().unwrap()]; + /// // write into out + /// decoder.decode_into(&mut out).unwrap(); + /// ``` + /// + /// + pub fn decode_into(&mut self, out: &mut [u8]) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + + let expected_size = self.output_buffer_size().unwrap(); + + if out.len() < expected_size { + // too small of a size + return Err(DecodeErrors::TooSmallOutput(expected_size, out.len())); + } + + // ensure we don't touch anyone else's scratch space + let out_len = core::cmp::min(out.len(), expected_size); + let out = &mut out[0..out_len]; + + if self.is_progressive { + self.decode_mcu_ycbcr_progressive(out) + } else { + self.decode_mcu_ycbcr_baseline(out) + } + } + + /// Read only headers from a jpeg image buffer + /// + /// This allows you to extract important information like + /// image width and height without decoding the full image + /// + /// # Examples + /// ```no_run + /// use zune_core::bytestream::ZCursor; + /// use zune_jpeg::{JpegDecoder}; + /// + /// let img_data = std::fs::read("a_valid.jpeg").unwrap(); + /// let mut decoder = JpegDecoder::new(ZCursor::new(&img_data)); + /// decoder.decode_headers().unwrap(); + /// + /// println!("Total decoder dimensions are : {:?} pixels",decoder.dimensions()); + /// println!("Number of components in the image are {}", decoder.info().unwrap().components); + /// ``` + /// # Errors + /// See DecodeErrors enum for list of possible errors during decoding + pub fn decode_headers(&mut self) -> Result<(), DecodeErrors> { + self.decode_headers_internal()?; + Ok(()) + } + /// Create a new decoder with the specified options to be used for decoding + /// an image + /// + /// # Arguments + /// - `buf`: The input buffer from where we will pull in compressed jpeg bytes from + /// - `options`: Options specific to this decoder instance + #[must_use] + pub fn new_with_options(buf: T, options: DecoderOptions) -> JpegDecoder { + JpegDecoder::default(options, buf) + } + + /// Set up-sampling routines in case an image is down sampled + pub(crate) fn set_upsampling(&mut self) -> Result<(), DecodeErrors> { + // no sampling, return early + // check if horizontal max ==1 + if self.h_max == self.v_max && self.h_max == 1 { + return Ok(()); + } + match (self.h_max, self.v_max) { + (1, 1) => { + self.sub_sample_ratio = SampleRatios::None; + } + (1, 2) => { + self.sub_sample_ratio = SampleRatios::V; + } + (2, 1) => { + self.sub_sample_ratio = SampleRatios::H; + } + (2, 2) => { + self.sub_sample_ratio = SampleRatios::HV; + } + _ => { + return Err(DecodeErrors::Format( + "Unknown down-sampling method, cannot continue".to_string() + )) + } + } + + for comp in &mut self.components { + let hs = self.h_max / comp.horizontal_sample; + let vs = self.v_max / comp.vertical_sample; + + let samp_factor = match (hs, vs) { + (1, 1) => { + comp.sample_ratio = SampleRatios::None; + upsample_no_op + } + (2, 1) => { + comp.sample_ratio = SampleRatios::H; + choose_horizontal_samp_function(self.options.use_unsafe()) + } + (1, 2) => { + comp.sample_ratio = SampleRatios::V; + choose_v_samp_function(self.options.use_unsafe()) + } + (2, 2) => { + comp.sample_ratio = SampleRatios::HV; + choose_hv_samp_function(self.options.use_unsafe()) + } + _ => { + return Err(DecodeErrors::Format( + "Unknown down-sampling method, cannot continue".to_string() + )) + } + }; + comp.setup_upsample_scanline(); + comp.up_sampler = samp_factor; + } + + return Ok(()); + } + #[must_use] + /// Get the width of the image as a u16 + /// + /// The width lies between 1 and 65535 + pub(crate) fn width(&self) -> u16 { + self.info.width + } + + /// Get the height of the image as a u16 + /// + /// The height lies between 1 and 65535 + #[must_use] + pub(crate) fn height(&self) -> u16 { + self.info.height + } + + /// Get image dimensions as a tuple of width and height + /// or `None` if the image hasn't been decoded. + /// + /// # Returns + /// - `Some(width,height)`: Image dimensions + /// - None : The image headers haven't been decoded + #[must_use] + pub const fn dimensions(&self) -> Option<(usize, usize)> { + return if self.headers_decoded { + Some((self.info.width as usize, self.info.height as usize)) + } else { + None + }; + } +} + +/// A struct representing Image Information +#[derive(Default, Clone, Eq, PartialEq)] +#[allow(clippy::module_name_repetitions)] +pub struct ImageInfo { + /// Width of the image + pub width: u16, + /// Height of image + pub height: u16, + /// PixelDensity + pub pixel_density: u8, + /// Start of frame markers + pub sof: SOFMarkers, + /// Horizontal sample + pub x_density: u16, + /// Vertical sample + pub y_density: u16, + /// Number of components + pub components: u8 +} + +impl ImageInfo { + /// Set width of the image + /// + /// Found in the start of frame + + pub(crate) fn set_width(&mut self, width: u16) { + self.width = width; + } + + /// Set height of the image + /// + /// Found in the start of frame + + pub(crate) fn set_height(&mut self, height: u16) { + self.height = height; + } + + /// Set the image density + /// + /// Found in the start of frame + + pub(crate) fn set_density(&mut self, density: u8) { + self.pixel_density = density; + } + + /// Set image Start of frame marker + /// + /// found in the Start of frame header + + pub(crate) fn set_sof_marker(&mut self, marker: SOFMarkers) { + self.sof = marker; + } + + /// Set image x-density(dots per pixel) + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_x(&mut self, sample: u16) { + self.x_density = sample; + } + + /// Set image y-density + /// + /// Found in the APP(0) marker + #[allow(dead_code)] + pub(crate) fn set_y(&mut self, sample: u16) { + self.y_density = sample; + } +} diff --git a/third_party/zune-jpeg/src/errors.rs b/third_party/zune-jpeg/src/errors.rs new file mode 100644 index 0000000..1410961 --- /dev/null +++ b/third_party/zune-jpeg/src/errors.rs @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Contains most common errors that may be encountered in decoding a Decoder +//! image + +use alloc::string::String; +use core::fmt::{Debug, Display, Formatter}; + +use zune_core::bytestream::ZByteIoError; + +use crate::misc::{ + START_OF_FRAME_EXT_AR, START_OF_FRAME_EXT_SEQ, START_OF_FRAME_LOS_SEQ, + START_OF_FRAME_LOS_SEQ_AR, START_OF_FRAME_PROG_DCT_AR +}; + +/// Common Decode errors +#[allow(clippy::module_name_repetitions)] +pub enum DecodeErrors { + /// Any other thing we do not know + Format(String), + /// Any other thing we do not know but we + /// don't need to allocate space on the heap + FormatStatic(&'static str), + /// Illegal Magic Bytes + IllegalMagicBytes(u16), + /// problems with the Huffman Tables in a Decoder file + HuffmanDecode(String), + /// Image has zero width + ZeroError, + /// Discrete Quantization Tables error + DqtError(String), + /// Start of scan errors + SosError(String), + /// Start of frame errors + SofError(String), + /// UnsupportedImages + Unsupported(UnsupportedSchemes), + /// MCU errors + MCUError(String), + /// Exhausted data + ExhaustedData, + /// Large image dimensions(Corrupted data)? + LargeDimensions(usize), + /// Too small output for size + TooSmallOutput(usize, usize), + + IoErrors(ZByteIoError) +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeErrors {} + +impl From<&'static str> for DecodeErrors { + fn from(data: &'static str) -> Self { + return Self::FormatStatic(data); + } +} + +impl From for DecodeErrors { + fn from(data: ZByteIoError) -> Self { + return Self::IoErrors(data); + } +} +impl Debug for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self + { + Self::Format(ref a) => write!(f, "{a:?}"), + Self::FormatStatic(a) => write!(f, "{:?}", &a), + + Self::HuffmanDecode(ref reason) => + { + write!(f, "Error decoding huffman values: {reason}") + } + Self::ZeroError => write!(f, "Image width or height is set to zero, cannot continue"), + Self::DqtError(ref reason) => write!(f, "Error parsing DQT segment. Reason:{reason}"), + Self::SosError(ref reason) => write!(f, "Error parsing SOS Segment. Reason:{reason}"), + Self::SofError(ref reason) => write!(f, "Error parsing SOF segment. Reason:{reason}"), + Self::IllegalMagicBytes(bytes) => + { + write!(f, "Error parsing image. Illegal start bytes:{bytes:X}") + } + Self::MCUError(ref reason) => write!(f, "Error in decoding MCU. Reason {reason}"), + Self::Unsupported(ref image_type) => + { + write!(f, "{image_type:?}") + } + Self::ExhaustedData => write!(f, "Exhausted data in the image"), + Self::LargeDimensions(ref dimensions) => write!( + f, + "Too large dimensions {dimensions},library supports up to {}", crate::decoder::MAX_DIMENSIONS + ), + Self::TooSmallOutput(expected, found) => write!(f, "Too small output, expected buffer with at least {expected} bytes but got one with {found} bytes"), + Self::IoErrors(error)=>write!(f,"I/O errors {error:?}"), + } + } +} + +impl Display for DecodeErrors { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } +} + +/// Contains Unsupported/Yet-to-be supported Decoder image encoding types. +#[derive(Eq, PartialEq, Copy, Clone)] +pub enum UnsupportedSchemes { + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Debug for UnsupportedSchemes { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match &self { + Self::ExtendedSequentialHuffman => { + write!(f, "The library cannot yet decode images encoded using Extended Sequential Huffman encoding scheme yet.") + } + Self::LosslessHuffman => { + write!(f, "The library cannot yet decode images encoded with Lossless Huffman encoding scheme") + } + Self::ExtendedSequentialDctArithmetic => { + write!(f,"The library cannot yet decode Images Encoded with Extended Sequential DCT Arithmetic scheme") + } + Self::ProgressiveDctArithmetic => { + write!(f,"The library cannot yet decode images encoded with Progressive DCT Arithmetic scheme") + } + Self::LosslessArithmetic => { + write!(f,"The library cannot yet decode images encoded with Lossless Arithmetic encoding scheme") + } + } + } +} + +impl UnsupportedSchemes { + #[must_use] + /// Create an unsupported scheme from an integer + /// + /// # Returns + /// `Some(UnsupportedScheme)` if the int refers to a specific scheme, + /// otherwise returns `None` + pub fn from_int(int: u8) -> Option { + let int = u16::from_be_bytes([0xff, int]); + + match int { + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} diff --git a/third_party/zune-jpeg/src/headers.rs b/third_party/zune-jpeg/src/headers.rs new file mode 100644 index 0000000..93126e2 --- /dev/null +++ b/third_party/zune-jpeg/src/headers.rs @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Decode Decoder markers/segments +//! +//! This file deals with decoding header information in a jpeg file +//! +use alloc::format; +use alloc::string::ToString; +use alloc::vec::Vec; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, error, trace, warn}; + +use crate::components::Components; +use crate::decoder::{ICCChunk, JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::misc::{SOFMarkers, UN_ZIGZAG}; + +///**B.2.4.2 Huffman table-specification syntax** +#[allow(clippy::similar_names, clippy::cast_sign_loss)] +pub(crate) fn parse_huffman( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> +where +{ + // Read the length of the Huffman table + let mut dht_length = i32::from(decoder.stream.get_u16_be_err()?.checked_sub(2).ok_or( + DecodeErrors::FormatStatic("Invalid Huffman length in image") + )?); + + while dht_length > 16 { + // HT information + let ht_info = decoder.stream.read_u8_err()?; + // third bit indicates whether the huffman encoding is DC or AC type + let dc_or_ac = (ht_info >> 4) & 0xF; + // Indicate the position of this table, should be less than 4; + let index = (ht_info & 0xF) as usize; + // read the number of symbols + let mut num_symbols: [u8; 17] = [0; 17]; + + if index >= MAX_COMPONENTS { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT index {index}, expected between 0 and 3" + ))); + } + + if dc_or_ac > 1 { + return Err(DecodeErrors::HuffmanDecode(format!( + "Invalid DHT position {dc_or_ac}, should be 0 or 1" + ))); + } + + decoder.stream.read_exact_bytes(&mut num_symbols[1..17])?; + + dht_length -= 1 + 16; + + let symbols_sum: i32 = num_symbols.iter().map(|f| i32::from(*f)).sum(); + + // The sum of the number of symbols cannot be greater than 256; + if symbols_sum > 256 { + return Err(DecodeErrors::FormatStatic( + "Encountered Huffman table with excessive length in DHT" + )); + } + if symbols_sum > dht_length { + return Err(DecodeErrors::HuffmanDecode(format!( + "Excessive Huffman table of length {symbols_sum} found when header length is {dht_length}" + ))); + } + dht_length -= symbols_sum; + // A table containing symbols in increasing code length + let mut symbols = [0; 256]; + + decoder + .stream + .read_exact_bytes(&mut symbols[0..(symbols_sum as usize)])?; + // store + match dc_or_ac { + 0 => { + decoder.dc_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + true, + decoder.is_progressive + )?); + } + _ => { + decoder.ac_huffman_tables[index] = Some(HuffmanTable::new( + &num_symbols, + symbols, + false, + decoder.is_progressive + )?); + } + } + } + + if dht_length > 0 { + return Err(DecodeErrors::FormatStatic("Bogus Huffman table definition")); + } + + Ok(()) +} + +///**B.2.4.1 Quantization table-specification syntax** +#[allow(clippy::cast_possible_truncation, clippy::needless_range_loop)] +pub(crate) fn parse_dqt(img: &mut JpegDecoder) -> Result<(), DecodeErrors> { + // read length + let mut qt_length = + img.stream + .get_u16_be_err()? + .checked_sub(2) + .ok_or(DecodeErrors::FormatStatic( + "Invalid DQT length. Length should be greater than 2" + ))?; + // A single DQT header may have multiple QT's + while qt_length > 0 { + let qt_info = img.stream.read_u8_err()?; + // 0 = 8 bit otherwise 16 bit dqt + let precision = (qt_info >> 4) as usize; + // last 4 bits give us position + let table_position = (qt_info & 0x0f) as usize; + let precision_value = 64 * (precision + 1); + + if (precision_value + 1) as u16 > qt_length { + return Err(DecodeErrors::DqtError(format!("Invalid QT table bytes left :{}. Too small to construct a valid qt table which should be {} long", qt_length, precision_value + 1))); + } + + let dct_table = match precision { + 0 => { + let mut qt_values = [0; 64]; + + img.stream.read_exact_bytes(&mut qt_values)?; + + qt_length -= (precision_value as u16) + 1 /*QT BIT*/; + // carry out un zig-zag here + un_zig_zag(&qt_values) + } + 1 => { + // 16 bit quantization tables + let mut qt_values = [0_u16; 64]; + + for i in 0..64 { + qt_values[i] = img.stream.get_u16_be_err()?; + } + qt_length -= (precision_value as u16) + 1; + + un_zig_zag(&qt_values) + } + _ => { + return Err(DecodeErrors::DqtError(format!( + "Expected QT precision value of either 0 or 1, found {precision:?}" + ))); + } + }; + + if table_position >= MAX_COMPONENTS { + return Err(DecodeErrors::DqtError(format!( + "Too large table position for QT :{table_position}, expected between 0 and 3" + ))); + } + + img.qt_tables[table_position] = Some(dct_table); + } + + return Ok(()); +} + +/// Section:`B.2.2 Frame header syntax` + +pub(crate) fn parse_start_of_frame( + sof: SOFMarkers, img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + if img.seen_sof { + return Err(DecodeErrors::SofError( + "Two Start of Frame Markers".to_string() + )); + } + // Get length of the frame header + let length = img.stream.get_u16_be_err()?; + // usually 8, but can be 12 and 16, we currently support only 8 + // so sorry about that 12 bit images + let dt_precision = img.stream.read_u8_err()?; + + if dt_precision != 8 { + return Err(DecodeErrors::SofError(format!( + "The library can only parse 8-bit images, the image has {dt_precision} bits of precision" + ))); + } + + img.info.set_density(dt_precision); + + // read and set the image height. + let img_height = img.stream.get_u16_be_err()?; + img.info.set_height(img_height); + + // read and set the image width + let img_width = img.stream.get_u16_be_err()?; + img.info.set_width(img_width); + + trace!("Image width :{}", img_width); + trace!("Image height :{}", img_height); + + if usize::from(img_width) > img.options.max_width() { + return Err(DecodeErrors::Format(format!("Image width {} greater than width limit {}. If use `set_limits` if you want to support huge images", img_width, img.options.max_width()))); + } + + if usize::from(img_height) > img.options.max_height() { + return Err(DecodeErrors::Format(format!("Image height {} greater than height limit {}. If use `set_limits` if you want to support huge images", img_height, img.options.max_height()))); + } + + // Check image width or height is zero + if img_width == 0 || img_height == 0 { + return Err(DecodeErrors::ZeroError); + } + + // Number of components for the image. + let num_components = img.stream.read_u8_err()?; + + if num_components == 0 { + return Err(DecodeErrors::SofError( + "Number of components cannot be zero.".to_string() + )); + } + + let expected = 8 + 3 * u16::from(num_components); + // length should be equal to num components + if length != expected { + return Err(DecodeErrors::SofError(format!( + "Length of start of frame differs from expected {expected},value is {length}" + ))); + } + + trace!("Image components : {}", num_components); + + if num_components == 1 { + // SOF sets the number of image components + // and that to us translates to setting input and output + // colorspaces to zero + img.input_colorspace = ColorSpace::Luma; + img.options = img.options.jpeg_set_out_colorspace(ColorSpace::Luma); + debug!("Overriding default colorspace set to Luma"); + } + if num_components == 4 && img.input_colorspace == ColorSpace::YCbCr { + trace!("Input image has 4 components, defaulting to CMYK colorspace"); + // https://entropymine.wordpress.com/2018/10/22/how-is-a-jpeg-images-color-type-determined/ + img.input_colorspace = ColorSpace::CMYK; + } + + // set number of components + img.info.components = num_components; + + let mut components = Vec::with_capacity(num_components as usize); + let mut temp = [0; 3]; + + for pos in 0..num_components { + // read 3 bytes for each component + img.stream.read_exact_bytes(&mut temp)?; + + // create a component. + let component = Components::from(temp, pos)?; + + components.push(component); + } + img.seen_sof = true; + + img.info.set_sof_marker(sof); + + img.components = components; + + Ok(()) +} + +/// Parse a start of scan data +pub(crate) fn parse_sos( + image: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // Scan header length + let ls = image.stream.get_u16_be_err()?; + // Number of image components in scan + let ns = image.stream.read_u8_err()?; + + let mut seen = [-1; { MAX_COMPONENTS + 1 }]; + + image.num_scans = ns; + + if ls != 6 + 2 * u16::from(ns) { + return Err(DecodeErrors::SosError(format!( + "Bad SOS length {ls},corrupt jpeg" + ))); + } + + // Check number of components. + if !(1..5).contains(&ns) { + return Err(DecodeErrors::SosError(format!( + "Number of components in start of scan should be less than 3 but more than 0. Found {ns}" + ))); + } + + if image.info.components == 0 { + return Err(DecodeErrors::FormatStatic( + "Error decoding SOF Marker, Number of components cannot be zero." + )); + } + + // consume spec parameters + for i in 0..ns { + // CS_i parameter, I don't need it so I might as well delete it + let id = image.stream.read_u8_err()?; + + if seen.contains(&i32::from(id)) { + return Err(DecodeErrors::SofError(format!( + "Duplicate ID {id} seen twice in the same component" + ))); + } + + seen[usize::from(i)] = i32::from(id); + // DC and AC huffman table position + // top 4 bits contain dc huffman destination table + // lower four bits contain ac huffman destination table + let y = image.stream.read_u8_err()?; + + let mut j = 0; + + while j < image.info.components { + if image.components[j as usize].id == id { + break; + } + + j += 1; + } + + if j == image.info.components { + return Err(DecodeErrors::SofError(format!( + "Invalid component id {}, expected a value between 0 and {}", + id, + image.components.len() + ))); + } + + image.components[usize::from(j)].dc_huff_table = usize::from((y >> 4) & 0xF); + image.components[usize::from(j)].ac_huff_table = usize::from(y & 0xF); + image.z_order[i as usize] = j as usize; + } + + // Collect the component spec parameters + // This is only needed for progressive images but I'll read + // them in order to ensure they are correct according to the spec + + // Extract progressive information + + // https://www.w3.org/Graphics/JPEG/itu-t81.pdf + // Page 42 + + // Start of spectral / predictor selection. (between 0 and 63) + image.spec_start = image.stream.read_u8_err()?; + // End of spectral selection + image.spec_end = image.stream.read_u8_err()?; + + let bit_approx = image.stream.read_u8_err()?; + // successive approximation bit position high + image.succ_high = bit_approx >> 4; + + if image.spec_end > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Se parameter {}, range should be 0-63", + image.spec_end + ))); + } + if image.spec_start > 63 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ss parameter {}, range should be 0-63", + image.spec_start + ))); + } + if image.succ_high > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Ah parameter {}, range should be 0-13", + image.succ_low + ))); + } + // successive approximation bit position low + image.succ_low = bit_approx & 0xF; + + if image.succ_low > 13 { + return Err(DecodeErrors::SosError(format!( + "Invalid Al parameter {}, range should be 0-13", + image.succ_low + ))); + } + + trace!( + "Ss={}, Se={} Ah={} Al={}", + image.spec_start, + image.spec_end, + image.succ_high, + image.succ_low + ); + + Ok(()) +} + +/// Parse Adobe App14 segment +pub(crate) fn parse_app14( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // skip length + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small APP14 length")); + } + if length < 14 { + return Err(DecodeErrors::FormatStatic( + "Too short of a length for App14 segment" + )); + } + if decoder.stream.peek_at(0, 5)? == b"Adobe" { + // move stream 6 bytes to remove adobe id + decoder.stream.skip(6)?; + // skip version, flags0 and flags1 + decoder.stream.skip(5)?; + // get color transform + let transform = decoder.stream.read_u8(); + // https://exiftool.org/TagNames/JPEG.html#Adobe + match transform { + 0 => decoder.input_colorspace = ColorSpace::CMYK, + 1 => decoder.input_colorspace = ColorSpace::YCbCr, + 2 => decoder.input_colorspace = ColorSpace::YCCK, + _ => { + return Err(DecodeErrors::Format(format!( + "Unknown Adobe colorspace {transform}" + ))) + } + } + // length = 2 + // adobe id = 6 + // version = 5 + // transform = 1 + length = length.saturating_sub(14); + } else if decoder.options.strict_mode() { + return Err(DecodeErrors::FormatStatic("Corrupt Adobe App14 segment")); + } else { + length = length.saturating_sub(2); + error!("Not a valid Adobe APP14 Segment"); + } + // skip any proceeding lengths. + // we do not need them + decoder.stream.skip(length)?; + + Ok(()) +} + +/// Parse the APP1 segment +/// +/// This contains the exif tag +pub(crate) fn parse_app1( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + // contains exif data + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small app1 length")); + } + // length bytes + length -= 2; + + if length > 6 && decoder.stream.peek_at(0, 6)? == b"Exif\x00\x00" { + trace!("Exif segment present"); + // skip bytes we read above + decoder.stream.skip(6)?; + length -= 6; + + let exif_bytes = decoder.stream.peek_at(0, length)?.to_vec(); + + decoder.exif_data = Some(exif_bytes); + } else { + warn!("Wrongly formatted exif tag"); + } + + decoder.stream.skip(length)?; + Ok(()) +} + +pub(crate) fn parse_app2( + decoder: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + let mut length = usize::from(decoder.stream.get_u16_be()); + + if length < 2 { + return Err(DecodeErrors::FormatStatic("Too small app2 segment")); + } + // length bytes + length -= 2; + + if length > 14 && decoder.stream.peek_at(0, 12)? == *b"ICC_PROFILE\0" { + trace!("ICC Profile present"); + // skip 12 bytes which indicate ICC profile + length -= 12; + decoder.stream.skip(12)?; + let seq_no = decoder.stream.read_u8(); + let num_markers = decoder.stream.read_u8(); + // deduct the two bytes we read above + length -= 2; + + let data = decoder.stream.peek_at(0, length)?.to_vec(); + + let icc_chunk = ICCChunk { + seq_no, + num_markers, + data + }; + decoder.icc_data.push(icc_chunk); + } + + decoder.stream.skip(length)?; + + Ok(()) +} + +/// Small utility function to print Un-zig-zagged quantization tables + +fn un_zig_zag(a: &[T]) -> [i32; 64] +where + T: Default + Copy, + i32: core::convert::From +{ + let mut output = [i32::default(); 64]; + + for i in 0..64 { + output[UN_ZIGZAG[i]] = i32::from(a[i]); + } + + output +} diff --git a/third_party/zune-jpeg/src/huffman.rs b/third_party/zune-jpeg/src/huffman.rs new file mode 100644 index 0000000..f5f12c2 --- /dev/null +++ b/third_party/zune-jpeg/src/huffman.rs @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! This file contains a single struct `HuffmanTable` that +//! stores Huffman tables needed during `BitStream` decoding. +#![allow(clippy::similar_names, clippy::module_name_repetitions)] + +use alloc::string::ToString; + +use crate::errors::DecodeErrors; + +/// Determines how many bits of lookahead we have for our bitstream decoder. + +pub const HUFF_LOOKAHEAD: u8 = 9; + +/// A struct which contains necessary tables for decoding a JPEG +/// huffman encoded bitstream + +pub struct HuffmanTable { + // element `[0]` of each array is unused + /// largest code of length k + pub(crate) maxcode: [i32; 18], + /// offset for codes of length k + /// Answers the question, where do code-lengths of length k end + /// Element 0 is unused + pub(crate) offset: [i32; 18], + /// lookup table for fast decoding + /// + /// top bits above HUFF_LOOKAHEAD contain the code length. + /// + /// Lower (8) bits contain the symbol in order of increasing code length. + pub(crate) lookup: [i32; 1 << HUFF_LOOKAHEAD], + + /// A table which can be used to decode small AC coefficients and + /// do an equivalent of receive_extend + pub(crate) ac_lookup: Option<[i16; 1 << HUFF_LOOKAHEAD]>, + + /// Directly represent contents of a JPEG DHT marker + /// + /// \# number of symbols with codes of length `k` bits + // bits[0] is unused + /// Symbols in order of increasing code length + pub(crate) values: [u8; 256] +} + +impl HuffmanTable { + pub fn new( + codes: &[u8; 17], values: [u8; 256], is_dc: bool, is_progressive: bool + ) -> Result { + let too_long_code = (i32::from(HUFF_LOOKAHEAD) + 1) << HUFF_LOOKAHEAD; + let mut p = HuffmanTable { + maxcode: [0; 18], + offset: [0; 18], + lookup: [too_long_code; 1 << HUFF_LOOKAHEAD], + values, + ac_lookup: None + }; + + p.make_derived_table(is_dc, is_progressive, codes)?; + + Ok(p) + } + + /// Create a new huffman tables with values that aren't fixed + /// used by fill_mjpeg_tables + pub fn new_unfilled( + codes: &[u8; 17], values: &[u8], is_dc: bool, is_progressive: bool + ) -> Result { + let mut buf = [0; 256]; + buf[..values.len()].copy_from_slice(values); + HuffmanTable::new(codes, buf, is_dc, is_progressive) + } + + /// Compute derived values for a Huffman table + /// + /// This routine performs some validation checks on the table + #[allow( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + clippy::too_many_lines, + clippy::needless_range_loop + )] + fn make_derived_table( + &mut self, is_dc: bool, _is_progressive: bool, bits: &[u8; 17] + ) -> Result<(), DecodeErrors> { + // build a list of code size + let mut huff_size = [0; 257]; + // Huffman code lengths + let mut huff_code: [u32; 257] = [0; 257]; + // figure C.1 make table of Huffman code length for each symbol + let mut p = 0; + + for l in 1..=16 { + let mut i = i32::from(bits[l]); + // table overrun is checked before ,so we dont need to check + while i != 0 { + huff_size[p] = l as u8; + p += 1; + i -= 1; + } + } + + huff_size[p] = 0; + + let num_symbols = p; + // Generate the codes themselves + // We also validate that the counts represent a legal Huffman code tree + let mut code = 0; + let mut si = i32::from(huff_size[0]); + + p = 0; + + while huff_size[p] != 0 { + while i32::from(huff_size[p]) == si { + huff_code[p] = code; + code += 1; + p += 1; + } + // maximum code of length si, pre-shifted by 16-k bits + self.maxcode[si as usize] = (code << (16 - si)) as i32; + // code is now 1 more than the last code used for code-length si; but + // it must still fit in si bits, since no code is allowed to be all ones. + if (code as i32) >= (1 << si) { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + + code <<= 1; + si += 1; + } + + // Figure F.15 generate decoding tables for bit-sequential decoding + p = 0; + + for l in 0..=16 { + if bits[l] == 0 { + // -1 if no codes of this length + self.maxcode[l] = -1; + } else { + // offset[l]=codes[index of 1st symbol of code length l + // minus minimum code of length l] + self.offset[l] = (p as i32) - (huff_code[p]) as i32; + p += usize::from(bits[l]); + } + } + + self.offset[17] = 0; + // we ensure that decode terminates + self.maxcode[17] = 0x000F_FFFF; + + /* + * Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0(left justified), indicating "too long"; + * (Note too long was set during initialization) + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + p = 0; + + for l in 1..=HUFF_LOOKAHEAD { + for _ in 1..=i32::from(bits[usize::from(l)]) { + // l -> Current code length, + // p => Its index in self.code and self.values + // Generate left justified code followed by all possible bit sequences + let mut look_bits = (huff_code[p] as usize) << (HUFF_LOOKAHEAD - l); + + for _ in 0..1 << (HUFF_LOOKAHEAD - l) { + self.lookup[look_bits] = + (i32::from(l) << HUFF_LOOKAHEAD) | i32::from(self.values[p]); + look_bits += 1; + } + + p += 1; + } + } + // build an ac table that does an equivalent of decode and receive_extend + if !is_dc { + let mut fast = [255; 1 << HUFF_LOOKAHEAD]; + // Iterate over number of symbols + for i in 0..num_symbols { + // get code size for an item + let s = huff_size[i]; + + if s <= HUFF_LOOKAHEAD { + // if it's lower than what we need for our lookup table create the table + let c = (huff_code[i] << (HUFF_LOOKAHEAD - s)) as usize; + let m = (1 << (HUFF_LOOKAHEAD - s)) as usize; + + for j in 0..m { + fast[c + j] = i as i16; + } + } + } + + // build a table that decodes both magnitude and value of small ACs in + // one go. + let mut fast_ac = [0; 1 << HUFF_LOOKAHEAD]; + + for i in 0..(1 << HUFF_LOOKAHEAD) { + let fast_v = fast[i]; + + if fast_v < 255 { + // get symbol value from AC table + let rs = self.values[fast_v as usize]; + // shift by 4 to get run length + let run = i16::from((rs >> 4) & 15); + // get magnitude bits stored at the lower 3 bits + let mag_bits = i16::from(rs & 15); + // length of the bit we've read + let len = i16::from(huff_size[fast_v as usize]); + + if mag_bits != 0 && (len + mag_bits) <= i16::from(HUFF_LOOKAHEAD) { + // magnitude code followed by receive_extend code + let mut k = (((i as i16) << len) & ((1 << HUFF_LOOKAHEAD) - 1)) + >> (i16::from(HUFF_LOOKAHEAD) - mag_bits); + let m = 1 << (mag_bits - 1); + + if k < m { + k += (!0_i16 << mag_bits) + 1; + }; + + // if result is small enough fit into fast ac table + if (-128..=127).contains(&k) { + fast_ac[i] = (k << 8) + (run << 4) + (len + mag_bits); + } + } + } + } + self.ac_lookup = Some(fast_ac); + } + + // Validate symbols as being reasonable + // For AC tables, we make no check, but accept all byte values 0..255 + // For DC tables, we require symbols to be in range 0..15 + if is_dc { + for i in 0..num_symbols { + let sym = self.values[i]; + + if sym > 15 { + return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string())); + } + } + } + + Ok(()) + } +} diff --git a/third_party/zune-jpeg/src/idct.rs b/third_party/zune-jpeg/src/idct.rs new file mode 100644 index 0000000..d2b6f06 --- /dev/null +++ b/third_party/zune-jpeg/src/idct.rs @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Routines for IDCT +//! +//! Essentially we provide 2 routines for IDCT, a scalar implementation and a not super optimized +//! AVX2 one, i'll talk about them here. +//! +//! There are 2 reasons why we have the avx one +//! 1. No one compiles with -C target-features=avx2 hence binaries won't probably take advantage(even +//! if it exists). +//! 2. AVX employs zero short circuit in a way the scalar code cannot employ it. +//! - AVX does this by checking for MCU's whose 63 AC coefficients are zero and if true, it writes +//! values directly, if false, it goes the long way of calculating. +//! - Although this can be trivially implemented in the scalar version, it generates code +//! I'm not happy width(scalar version that basically loops and that is too many branches for me) +//! The avx one does a better job of using bitwise or's with (`_mm256_or_si256`) which is magnitudes of faster +//! than anything I could come up with +//! +//! The AVX code also has some cool transpose_u16 instructions which look so complicated to be cool +//! (spoiler alert, i barely understand how it works, that's why I credited the owner). +//! +#![allow( + clippy::excessive_precision, + clippy::unreadable_literal, + clippy::module_name_repetitions, + unused_parens, + clippy::wildcard_imports +)] + +use zune_core::log::debug; +use zune_core::options::DecoderOptions; + +use crate::decoder::IDCTPtr; +use crate::idct::scalar::idct_int; + +#[cfg(feature = "x86")] +pub mod avx2; +#[cfg(feature = "neon")] +pub mod neon; + +pub mod scalar; + +/// Choose an appropriate IDCT function +#[allow(unused_variables)] +pub fn choose_idct_func(options: &DecoderOptions) -> IDCTPtr { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[cfg(feature = "x86")] + { + if options.use_avx2() { + debug!("Using vector integer IDCT"); + // use avx one + return crate::idct::avx2::idct_avx2; + } + } + #[cfg(target_arch = "aarch64")] + #[cfg(feature = "neon")] + { + if options.use_neon() { + debug!("Using vector integer IDCT"); + return crate::idct::neon::idct_neon; + } + } + debug!("Using scalar integer IDCT"); + // use generic one + return idct_int; +} + +#[cfg(test)] +#[allow(unreachable_code)] +#[allow(dead_code)] +mod tests { + use super::*; + + #[test] + fn idct_test0() { + let stride = 8; + let mut coeff = [10; 64]; + let mut coeff2 = [10; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test1() { + let stride = 8; + let mut coeff = [14; 64]; + let mut coeff2 = [14; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_test2() { + let stride = 8; + let mut coeff = [0; 64]; + coeff[0] = 255; + coeff[63] = -256; + let mut coeff2 = coeff; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + #[test] + fn do_idct_zeros() { + let stride = 8; + let mut coeff = [0; 64]; + let mut coeff2 = [0; 64]; + let mut output_scalar = [0; 64]; + let mut output_vector = [0; 64]; + idct_fnc()(&mut coeff, &mut output_vector, stride); + idct_int(&mut coeff2, &mut output_scalar, stride); + assert_eq!(output_scalar, output_vector, "IDCT and scalar do not match"); + } + + fn idct_fnc() -> IDCTPtr { + #[cfg(feature = "neon")] + #[cfg(target_arch = "aarch64")] + { + use crate::idct::neon::idct_neon; + return idct_neon; + } + + #[cfg(feature = "x86")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + use crate::idct::avx2::idct_avx2; + return idct_avx2; + } + + idct_int + } +} diff --git a/third_party/zune-jpeg/src/idct/avx2.rs b/third_party/zune-jpeg/src/idct/avx2.rs new file mode 100644 index 0000000..0f2f195 --- /dev/null +++ b/third_party/zune-jpeg/src/idct/avx2.rs @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "x86")] +#![allow(dead_code)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +/// SAFETY +/// ------ +/// +/// It is the responsibility of the CALLER to ensure that this function is +/// called in contexts where the CPU supports it +/// +/// +/// For documentation see module docs. + +pub fn idct_avx2(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + unsafe { + // We don't call this method directly because we need to flag the code function + // with #[target_feature] so that the compiler does do weird stuff with + // it + idct_int_avx2_inner(in_vector, out_vector, stride); + } +} + +#[target_feature(enable = "avx2")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_int_avx2_inner( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let rw0 = _mm256_loadu_si256(in_vector[00..].as_ptr().cast()); + let rw1 = _mm256_loadu_si256(in_vector[08..].as_ptr().cast()); + let rw2 = _mm256_loadu_si256(in_vector[16..].as_ptr().cast()); + let rw3 = _mm256_loadu_si256(in_vector[24..].as_ptr().cast()); + let rw4 = _mm256_loadu_si256(in_vector[32..].as_ptr().cast()); + let rw5 = _mm256_loadu_si256(in_vector[40..].as_ptr().cast()); + let rw6 = _mm256_loadu_si256(in_vector[48..].as_ptr().cast()); + let rw7 = _mm256_loadu_si256(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + let rw8 = _mm256_loadu_si256(in_vector[1..].as_ptr().cast()); + + let zero = _mm256_setzero_si256(); + + let mut non_zero = 0; + + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw8, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw1, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi32(rw2, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw3, zero)); + + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw4, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw5, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw6, zero)); + non_zero += _mm256_movemask_epi8(_mm256_cmpeq_epi64(rw7, zero)); + + if non_zero == -8 { + // AC terms all zero, idct of the block is is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + let idct_value = _mm_set1_epi16(((in_vector[0] >> 3) + 128).clamp(0, 255) as i16); + + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + _mm_storeu_si128( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + let mut row0 = YmmRegister { mm256: rw0 }; + let mut row1 = YmmRegister { mm256: rw1 }; + let mut row2 = YmmRegister { mm256: rw2 }; + let mut row3 = YmmRegister { mm256: rw3 }; + + let mut row4 = YmmRegister { mm256: rw4 }; + let mut row5 = YmmRegister { mm256: rw5 }; + let mut row6 = YmmRegister { mm256: rw6 }; + let mut row7 = YmmRegister { mm256: rw7 }; + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = YmmRegister { + mm256: _mm256_slli_epi32((row0 + row4).mm256, 12) + }; + let mut t1 = YmmRegister { + mm256: _mm256_slli_epi32((row0 - row4).mm256, 12) + }; + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0.mm256 = _mm256_srai_epi32((x0 + t3).mm256, $scale); + row1.mm256 = _mm256_srai_epi32((x1 + t2).mm256, $scale); + row2.mm256 = _mm256_srai_epi32((x2 + t1).mm256, $scale); + row3.mm256 = _mm256_srai_epi32((x3 + t0).mm256, $scale); + + row4.mm256 = _mm256_srai_epi32((x3 - t0).mm256, $scale); + row5.mm256 = _mm256_srai_epi32((x2 - t1).mm256, $scale); + row6.mm256 = _mm256_srai_epi32((x1 - t2).mm256, $scale); + row7.mm256 = _mm256_srai_epi32((x0 - t3).mm256, $scale); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // Pack i32 to i16's, + // clamp them to be between 0-255 + // Undo shuffling + // Store back to array + macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt) => { + let a = _mm256_packs_epi32($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp_avx(a); + + // /Undo shuffling + let c = _mm256_permute4x64_epi64(b, shuffle(3, 1, 2, 0)); + + // store first vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<0>(c) + ); + $index += stride; + // second vector + _mm_storeu_si128( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + _mm256_extractf128_si256::<1>(c) + ); + $index += stride; + }; + } + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector); +} + +#[inline] +#[target_feature(enable = "avx2")] +unsafe fn clamp_avx(reg: __m256i) -> __m256i { + let min_s = _mm256_set1_epi16(0); + let max_s = _mm256_set1_epi16(255); + + let max_v = _mm256_max_epi16(reg, min_s); //max(a,0) + let min_v = _mm256_min_epi16(max_v, max_s); //min(max(a,0),255) + return min_v; +} + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + ((z << 6) | (y << 4) | (x << 2) | w) +} diff --git a/third_party/zune-jpeg/src/idct/neon.rs b/third_party/zune-jpeg/src/idct/neon.rs new file mode 100644 index 0000000..cba9f7d --- /dev/null +++ b/third_party/zune-jpeg/src/idct/neon.rs @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(target_arch = "aarch64")] +//! AVX optimised IDCT. +//! +//! Okay not thaat optimised. +//! +//! +//! # The implementation +//! The implementation is neatly broken down into two operations. +//! +//! 1. Test for zeroes +//! > There is a shortcut method for idct where when all AC values are zero, we can get the answer really quickly. +//! by scaling the 1/8th of the DCT coefficient of the block to the whole block and level shifting. +//! +//! 2. If above fails, we proceed to carry out IDCT as a two pass one dimensional algorithm. +//! IT does two whole scans where it carries out IDCT on all items +//! After each successive scan, data is transposed in register(thank you x86 SIMD powers). and the second +//! pass is carried out. +//! +//! The code is not super optimized, it produces bit identical results with scalar code hence it's +//! `mm256_add_epi16` +//! and it also has the advantage of making this implementation easy to maintain. + +#![cfg(feature = "neon")] + +use core::arch::aarch64::*; + +use crate::unsafe_utils::{transpose, YmmRegister}; + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +/// SAFETY +/// ------ +/// +/// It is the responsibility of the CALLER to ensure that this function is +/// called in contexts where the CPU supports it +/// +/// +/// For documentation see module docs. + +pub fn idct_neon(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + unsafe { + // We don't call this method directly because we need to flag the code function + // with #[target_feature] so that the compiler does do weird stuff with + // it + idct_int_neon_inner(in_vector, out_vector, stride); + } +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn pack_16(a: int32x4x2_t) -> int16x8_t { + vcombine_s16(vqmovn_s32(a.0), vqmovn_s32(a.1)) +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn condense_bottom_16(a: int32x4x2_t, b: int32x4x2_t) -> int16x8x2_t { + int16x8x2_t(pack_16(a), pack_16(b)) +} + +#[target_feature(enable = "neon")] +#[allow( + clippy::too_many_lines, + clippy::cast_possible_truncation, + clippy::similar_names, + clippy::op_ref, + unused_assignments, + clippy::zero_prefixed_literal +)] +pub unsafe fn idct_int_neon_inner( + in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize +) { + let mut pos = 0; + + // load into registers + // + // We sign extend i16's to i32's and calculate them with extended precision and + // later reduce them to i16's when we are done carrying out IDCT + + let mut row0 = YmmRegister::load(in_vector[00..].as_ptr().cast()); + let mut row1 = YmmRegister::load(in_vector[08..].as_ptr().cast()); + let mut row2 = YmmRegister::load(in_vector[16..].as_ptr().cast()); + let mut row3 = YmmRegister::load(in_vector[24..].as_ptr().cast()); + let mut row4 = YmmRegister::load(in_vector[32..].as_ptr().cast()); + let mut row5 = YmmRegister::load(in_vector[40..].as_ptr().cast()); + let mut row6 = YmmRegister::load(in_vector[48..].as_ptr().cast()); + let mut row7 = YmmRegister::load(in_vector[56..].as_ptr().cast()); + + // Forward DCT and quantization may cause all the AC terms to be zero, for such + // cases we can try to accelerate it + + // Basically the poop is that whenever the array has 63 zeroes, its idct is + // (arr[0]>>3)or (arr[0]/8) propagated to all the elements. + // We first test to see if the array contains zero elements and if it does, we go the + // short way. + // + // This reduces IDCT overhead from about 39% to 18 %, almost half + + // Do another load for the first row, we don't want to check DC value, because + // we only care about AC terms + // TODO this should be a shift/shuffle, not a likely unaligned load + let row8 = YmmRegister::load(in_vector[1..].as_ptr().cast()); + + let or_tree = (((row1 | row8) | (row2 | row3)) | ((row4 | row5) | (row6 | row7))); + + if or_tree.all_zero() { + // AC terms all zero, idct of the block is is ( coeff[0] * qt[0] )/8 + 128 (bias) + // (and clamped to 255) + let clamped_16 = ((in_vector[0] >> 3) + 128).clamp(0, 255) as i16; + let idct_value = vdupq_n_s16(clamped_16); + + macro_rules! store { + ($pos:tt,$value:tt) => { + // store + vst1q_s16( + out_vector + .get_mut($pos..$pos + 8) + .unwrap() + .as_mut_ptr() + .cast(), + $value + ); + $pos += stride; + }; + } + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + store!(pos, idct_value); + + return; + } + + macro_rules! dct_pass { + ($SCALE_BITS:tt,$scale:tt) => { + // There are a lot of ways to do this + // but to keep it simple(and beautiful), ill make a direct translation of the + // scalar code to also make this code fully transparent(this version and the non + // avx one should produce identical code.) + + // Compiler does a pretty good job of optimizing add + mul pairs + // into multiply-acumulate pairs + + // even part + let p1 = (row2 + row6) * 2217; + + let mut t2 = p1 + row6 * -7567; + let mut t3 = p1 + row2 * 3135; + + let mut t0 = (row0 + row4).const_shl::<12>(); + let mut t1 = (row0 - row4).const_shl::<12>(); + + let x0 = t0 + t3 + $SCALE_BITS; + let x3 = t0 - t3 + $SCALE_BITS; + let x1 = t1 + t2 + $SCALE_BITS; + let x2 = t1 - t2 + $SCALE_BITS; + + let p3 = row7 + row3; + let p4 = row5 + row1; + let p1 = row7 + row1; + let p2 = row5 + row3; + let p5 = (p3 + p4) * 4816; + + t0 = row7 * 1223; + t1 = row5 * 8410; + t2 = row3 * 12586; + t3 = row1 * 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + (p2 * -10497); + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + row0 = (x0 + t3).const_shra::<$scale>(); + row1 = (x1 + t2).const_shra::<$scale>(); + row2 = (x2 + t1).const_shra::<$scale>(); + row3 = (x3 + t0).const_shra::<$scale>(); + + row4 = (x3 - t0).const_shra::<$scale>(); + row5 = (x2 - t1).const_shra::<$scale>(); + row6 = (x1 - t2).const_shra::<$scale>(); + row7 = (x0 - t3).const_shra::<$scale>(); + }; + } + + // Process rows + dct_pass!(512, 10); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // process columns + dct_pass!(SCALE_BITS, 17); + transpose( + &mut row0, &mut row1, &mut row2, &mut row3, &mut row4, &mut row5, &mut row6, &mut row7 + ); + + // Pack i32 to i16's, + // clamp them to be between 0-255 + // Undo shuffling + // Store back to array + + // This could potentially be reorganized to take advantage of the multi-register stores + macro_rules! permute_store { + ($x:tt,$y:tt,$index:tt,$out:tt) => { + let a = condense_bottom_16($x, $y); + + // Clamp the values after packing, we can clamp more values at once + let b = clamp256_neon(a); + + // store first vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.0 + ); + $index += stride; + // second vector + vst1q_s16( + ($out) + .get_mut($index..$index + 8) + .unwrap() + .as_mut_ptr() + .cast(), + b.1 + ); + $index += stride; + }; + } + // Pack and write the values back to the array + permute_store!((row0.mm256), (row1.mm256), pos, out_vector); + permute_store!((row2.mm256), (row3.mm256), pos, out_vector); + permute_store!((row4.mm256), (row5.mm256), pos, out_vector); + permute_store!((row6.mm256), (row7.mm256), pos, out_vector); +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp_neon(reg: int16x8_t) -> int16x8_t { + let min_s = vdupq_n_s16(0); + let max_s = vdupq_n_s16(255); + + let max_v = vmaxq_s16(reg, min_s); //max(a,0) + let min_v = vminq_s16(max_v, max_s); //min(max(a,0),255) + min_v +} + +#[inline] +#[target_feature(enable = "neon")] +unsafe fn clamp256_neon(reg: int16x8x2_t) -> int16x8x2_t { + int16x8x2_t(clamp_neon(reg.0), clamp_neon(reg.1)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_neon_clamp_256() { + unsafe { + let vals: [i16; 16] = [-1, -2, -3, 4, 256, 257, 258, 240, -1, 290, 2, 3, 4, 5, 6, 7]; + let loaded = vld1q_s16_x2(vals.as_ptr().cast()); + let shuffled = clamp256_neon(loaded); + + let mut result: [i16; 16] = [0; 16]; + + vst1q_s16_x2(result.as_mut_ptr().cast(), shuffled); + + assert_eq!( + result, + [0, 0, 0, 4, 255, 255, 255, 240, 0, 255, 2, 3, 4, 5, 6, 7] + ) + } + } +} diff --git a/third_party/zune-jpeg/src/idct/scalar.rs b/third_party/zune-jpeg/src/idct/scalar.rs new file mode 100644 index 0000000..3120381 --- /dev/null +++ b/third_party/zune-jpeg/src/idct/scalar.rs @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Platform independent IDCT algorithm +//! +//! Not as fast as AVX one. + +const SCALE_BITS: i32 = 512 + 65536 + (128 << 17); + +#[allow(unused_assignments)] +#[allow( + clippy::too_many_lines, + clippy::op_ref, + clippy::cast_possible_truncation +)] +pub fn idct_int(in_vector: &mut [i32; 64], out_vector: &mut [i16], stride: usize) { + // Temporary variables. + + let mut pos = 0; + + let mut i = 0; + // Don't check for zeroes inside loop, lift it and check outside + // we want to accelerate the case with 63 0 ac coeff + if &in_vector[1..] == &[0_i32; 63] { + // okay then if you work, yay, let's write you really quick + let coeff = [(((in_vector[0] >> 3) + 128) as i16).clamp(0, 255); 8]; + + macro_rules! store { + ($index:tt) => { + // position of the MCU + let mcu_stride: &mut [i16; 8] = out_vector + .get_mut($index..$index + 8) + .unwrap() + .try_into() + .unwrap(); + // copy coefficients + mcu_stride.copy_from_slice(&coeff); + // increment index + $index += stride; + }; + } + // write to four positions + store!(pos); + store!(pos); + store!(pos); + store!(pos); + + store!(pos); + store!(pos); + store!(pos); + store!(pos); + } else { + // because the compiler fails to see that it can be auto_vectorised so i'll + // leave it here check out [idct_int_slow, and idct_int_1D to get what i mean ] https://godbolt.org/z/8hqW9z9j9 + for ptr in 0..8 { + let p2 = in_vector[ptr + 16]; + let p3 = in_vector[ptr + 48]; + + let p1 = (p2 + p3).wrapping_mul(2217); + + let t2 = p1 + p3 * -7567; + let t3 = p1 + p2 * 3135; + + let p2 = in_vector[ptr]; + let p3 = in_vector[32 + ptr]; + let t0 = fsh(p2 + p3); + let t1 = fsh(p2 - p3); + + let x0 = t0 + t3 + 512; + let x3 = t0 - t3 + 512; + let x1 = t1 + t2 + 512; + let x2 = t1 - t2 + 512; + + // odd part + let mut t0 = in_vector[ptr + 56]; + let mut t1 = in_vector[ptr + 40]; + let mut t2 = in_vector[ptr + 24]; + let mut t3 = in_vector[ptr + 8]; + + let p3 = t0 + t2; + let p4 = t1 + t3; + let p1 = t0 + t3; + let p2 = t1 + t2; + let p5 = (p3 + p4) * 4816; + + t0 *= 1223; + t1 *= 8410; + t2 *= 12586; + t3 *= 6149; + + let p1 = p5 + p1 * -3685; + let p2 = p5 + p2 * -10497; + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + in_vector[ptr] = (x0 + t3) >> 10; + in_vector[ptr + 8] = (x1 + t2) >> 10; + in_vector[ptr + 16] = (x2 + t1) >> 10; + in_vector[ptr + 24] = (x3 + t0) >> 10; + in_vector[ptr + 32] = (x3 - t0) >> 10; + in_vector[ptr + 40] = (x2 - t1) >> 10; + in_vector[ptr + 48] = (x1 - t2) >> 10; + in_vector[ptr + 56] = (x0 - t3) >> 10; + } + + // This is vectorised in architectures supporting SSE 4.1 + while i < 64 { + // We won't try to short circuit here because it rarely works + + // Even part + let p2 = in_vector[i + 2]; + let p3 = in_vector[i + 6]; + + let p1 = (p2 + p3) * 2217; + let t2 = p1 + p3 * -7567; + let t3 = p1 + p2 * 3135; + + let p2 = in_vector[i]; + let p3 = in_vector[i + 4]; + + let t0 = fsh(p2 + p3); + let t1 = fsh(p2 - p3); + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + let x0 = t0 + t3 + SCALE_BITS; + let x3 = t0 - t3 + SCALE_BITS; + let x1 = t1 + t2 + SCALE_BITS; + let x2 = t1 - t2 + SCALE_BITS; + // odd part + let mut t0 = in_vector[i + 7]; + let mut t1 = in_vector[i + 5]; + let mut t2 = in_vector[i + 3]; + let mut t3 = in_vector[i + 1]; + + let p3 = t0 + t2; + let p4 = t1 + t3; + let p1 = t0 + t3; + let p2 = t1 + t2; + let p5 = (p3 + p4) * f2f(1.175875602); + + t0 = t0.wrapping_mul(1223); + t1 = t1.wrapping_mul(8410); + t2 = t2.wrapping_mul(12586); + t3 = t3.wrapping_mul(6149); + + let p1 = p5 + p1 * -3685; + let p2 = p5 + p2 * -10497; + let p3 = p3 * -8034; + let p4 = p4 * -1597; + + t3 += p1 + p4; + t2 += p2 + p3; + t1 += p2 + p4; + t0 += p1 + p3; + + let out: &mut [i16; 8] = out_vector + .get_mut(pos..pos + 8) + .unwrap() + .try_into() + .unwrap(); + + out[0] = clamp((x0 + t3) >> 17); + out[1] = clamp((x1 + t2) >> 17); + out[2] = clamp((x2 + t1) >> 17); + out[3] = clamp((x3 + t0) >> 17); + out[4] = clamp((x3 - t0) >> 17); + out[5] = clamp((x2 - t1) >> 17); + out[6] = clamp((x1 - t2) >> 17); + out[7] = clamp((x0 - t3) >> 17); + + i += 8; + + pos += stride; + } + } +} + +#[inline] +#[allow(clippy::cast_possible_truncation)] +/// Multiply a number by 4096 +fn f2f(x: f32) -> i32 { + (x * 4096.0 + 0.5) as i32 +} + +#[inline] +/// Multiply a number by 4096 +fn fsh(x: i32) -> i32 { + x << 12 +} + +/// Clamp values between 0 and 255 +#[inline] +#[allow(clippy::cast_possible_truncation)] +fn clamp(a: i32) -> i16 { + a.clamp(0, 255) as i16 +} diff --git a/third_party/zune-jpeg/src/lib.rs b/third_party/zune-jpeg/src/lib.rs new file mode 100644 index 0000000..d20ab4f --- /dev/null +++ b/third_party/zune-jpeg/src/lib.rs @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!This crate provides a library for decoding valid +//! ITU-T Rec. T.851 (09/2005) ITU-T T.81 (JPEG-1) or JPEG images. +//! +//! +//! +//! # Features +//! - SSE and AVX accelerated functions to speed up certain decoding operations +//! - FAST and accurate 32 bit IDCT algorithm +//! - Fast color convert functions +//! - RGBA and RGBX (4-Channel) color conversion functions +//! - YCbCr to Luma(Grayscale) conversion. +//! +//! # Usage +//! Add zune-jpeg to the dependencies in the project Cargo.toml +//! +//! ```toml +//! [dependencies] +//! zune_jpeg = "0.3" +//! ``` +//! # Examples +//! +//! ## Decode a JPEG file with default arguments. +//!```no_run +//! use std::fs::read; +//! use std::io::BufReader; +//! use zune_jpeg::JpegDecoder; +//! let file_contents = BufReader::new(std::fs::File::open("a_jpeg.file").unwrap()); +//! let mut decoder = JpegDecoder::new(file_contents); +//! let mut pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Decode a JPEG file to RGBA format +//! +//! - Other (limited) supported formats are and BGR, BGRA +//! +//!```no_run +//! use zune_core::bytestream::ZCursor; +//! use zune_core::colorspace::ColorSpace; +//! use zune_core::options::DecoderOptions; +//! use zune_jpeg::JpegDecoder; +//! +//! let mut options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::RGBA); +//! +//! let mut decoder = JpegDecoder::new_with_options(ZCursor::new(&[]),options); +//! let pixels = decoder.decode().unwrap(); +//! ``` +//! +//! ## Decode an image and get it's width and height. +//!```no_run +//! use zune_core::bytestream::ZCursor; +//! use zune_jpeg::JpegDecoder; +//! +//! let mut decoder = JpegDecoder::new(ZCursor::new(&[])); +//! decoder.decode_headers().unwrap(); +//! let image_info = decoder.info().unwrap(); +//! println!("{},{}",image_info.width,image_info.height) +//! ``` +//! # Crate features. +//! This crate tries to be as minimal as possible while being extensible +//! enough to handle the complexities arising from parsing different types +//! of jpeg images. +//! +//! Safety is a top concern that is why we provide both static ways to disable unsafe code, +//! disabling x86 feature, and dynamic ,by using [`DecoderOptions::set_use_unsafe(false)`], +//! both of these disable platform specific optimizations, which reduce the speed of decompression. +//! +//! Please do note that careful consideration has been taken to ensure that the unsafe paths +//! are only unsafe because they depend on platform specific intrinsics, hence no need to disable them +//! +//! The crate tries to decode as many images as possible, as a best effort, even those violating the standard +//! , this means a lot of images may get silent warnings and wrong output, but if you are sure you will be handling +//! images that follow the spec, set `ZuneJpegOptions::set_strict` to true. +//! +//![`DecoderOptions::set_use_unsafe(false)`]: https://docs.rs/zune-core/0.2.1/zune_core/options/struct.DecoderOptions.html#method.set_use_unsafe + +#![warn( + clippy::correctness, + clippy::perf, + clippy::pedantic, + clippy::inline_always, + clippy::missing_errors_doc, + clippy::panic +)] +#![allow( + clippy::needless_return, + clippy::similar_names, + clippy::inline_always, + clippy::similar_names, + clippy::doc_markdown, + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc +)] +// no_std compatibility +#![deny(clippy::std_instead_of_alloc, clippy::alloc_instead_of_core)] +#![cfg_attr(not(feature = "x86"), forbid(unsafe_code))] +#![cfg_attr(not(feature = "std"), no_std)] +#![macro_use] +extern crate alloc; +extern crate core; + +pub use zune_core; + +pub use crate::decoder::{ImageInfo, JpegDecoder}; + +mod bitstream; +mod color_convert; +mod components; +mod decoder; +pub mod errors; +mod headers; +mod huffman; +#[cfg(not(fuzzing))] +mod idct; +#[cfg(fuzzing)] +pub mod idct; +mod marker; +mod mcu; +mod mcu_prog; +mod misc; +mod unsafe_utils; +mod unsafe_utils_avx2; +mod unsafe_utils_neon; +mod upsampler; +mod worker; diff --git a/third_party/zune-jpeg/src/marker.rs b/third_party/zune-jpeg/src/marker.rs new file mode 100644 index 0000000..f2d6ac1 --- /dev/null +++ b/third_party/zune-jpeg/src/marker.rs @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![allow(clippy::upper_case_acronyms)] + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Marker { + /// Start Of Frame markers + /// + /// - SOF(0): Baseline DCT (Huffman coding) + /// - SOF(1): Extended sequential DCT (Huffman coding) + /// - SOF(2): Progressive DCT (Huffman coding) + /// - SOF(3): Lossless (sequential) (Huffman coding) + /// - SOF(5): Differential sequential DCT (Huffman coding) + /// - SOF(6): Differential progressive DCT (Huffman coding) + /// - SOF(7): Differential lossless (sequential) (Huffman coding) + /// - SOF(9): Extended sequential DCT (arithmetic coding) + /// - SOF(10): Progressive DCT (arithmetic coding) + /// - SOF(11): Lossless (sequential) (arithmetic coding) + /// - SOF(13): Differential sequential DCT (arithmetic coding) + /// - SOF(14): Differential progressive DCT (arithmetic coding) + /// - SOF(15): Differential lossless (sequential) (arithmetic coding) + SOF(u8), + /// Define Huffman table(s) + DHT, + /// Define arithmetic coding conditioning(s) + DAC, + /// Restart with modulo 8 count `m` + RST(u8), + /// Start of image + SOI, + /// End of image + EOI, + /// Start of scan + SOS, + /// Define quantization table(s) + DQT, + /// Define number of lines + DNL, + /// Define restart interval + DRI, + /// Reserved for application segments + APP(u8), + /// Comment + COM +} + +impl Marker { + pub fn from_u8(n: u8) -> Option { + use self::Marker::{APP, COM, DAC, DHT, DNL, DQT, DRI, EOI, RST, SOF, SOI, SOS}; + + match n { + 0xFE => Some(COM), + 0xC0 => Some(SOF(0)), + 0xC1 => Some(SOF(1)), + 0xC2 => Some(SOF(2)), + 0xC4 => Some(DHT), + 0xCC => Some(DAC), + 0xD0 => Some(RST(0)), + 0xD1 => Some(RST(1)), + 0xD2 => Some(RST(2)), + 0xD3 => Some(RST(3)), + 0xD4 => Some(RST(4)), + 0xD5 => Some(RST(5)), + 0xD6 => Some(RST(6)), + 0xD7 => Some(RST(7)), + 0xD8 => Some(SOI), + 0xD9 => Some(EOI), + 0xDA => Some(SOS), + 0xDB => Some(DQT), + 0xDC => Some(DNL), + 0xDD => Some(DRI), + 0xE0 => Some(APP(0)), + 0xE1 => Some(APP(1)), + 0xE2 => Some(APP(2)), + 0xEE => Some(APP(14)), + _ => None + } + } +} diff --git a/third_party/zune-jpeg/src/mcu.rs b/third_party/zune-jpeg/src/mcu.rs new file mode 100644 index 0000000..2d7b406 --- /dev/null +++ b/third_party/zune-jpeg/src/mcu.rs @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::{format, vec}; +use core::cmp::min; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::colorspace::ColorSpace::Luma; +use zune_core::log::{error, trace, warn}; + +use crate::bitstream::BitStream; +use crate::components::SampleRatios; +use crate::decoder::MAX_COMPONENTS; +use crate::errors::DecodeErrors; +use crate::marker::Marker; +use crate::misc::{calculate_padded_width, setup_component_params}; +use crate::worker::{color_convert, upsample}; +use crate::JpegDecoder; + +/// The size of a DC block for a MCU. + +pub const DCT_BLOCK: usize = 64; + +impl JpegDecoder { + /// Check for existence of DC and AC Huffman Tables + pub(crate) fn check_tables(&self) -> Result<(), DecodeErrors> { + // check that dc and AC tables exist outside the hot path + for component in &self.components { + let _ = &self + .dc_huffman_tables + .get(component.dc_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman DC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No DC table for component {:?}", + component.component_id + )) + })?; + + let _ = &self + .ac_huffman_tables + .get(component.ac_huff_table) + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No Huffman AC table for component {:?} ", + component.component_id + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::HuffmanDecode(format!( + "No AC table for component {:?}", + component.component_id + )) + })?; + } + Ok(()) + } + + /// Decode MCUs and carry out post processing. + /// + /// This is the main decoder loop for the library, the hot path. + /// + /// Because of this, we pull in some very crazy optimization tricks hence readability is a pinch + /// here. + #[allow( + clippy::similar_names, + clippy::too_many_lines, + clippy::cast_possible_truncation + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_baseline( + &mut self, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + // check dc and AC tables + self.check_tables()?; + + let (mut mcu_width, mut mcu_height); + + if self.is_interleaved { + // set upsampling functions + self.set_upsampling()?; + + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided bu 8. + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + if self.input_colorspace.num_components() > self.components.len() { + let msg = format!( + " Expected {} number of components but found {}", + self.input_colorspace.num_components(), + self.components.len() + ); + return Err(DecodeErrors::Format(msg)); + } + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + + self.reset_params(); + + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } + let width = usize::from(self.info.width); + + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + let mut stream = BitStream::new(); + let mut tmp = [0_i32; DCT_BLOCK]; + + let comp_len = self.components.len(); + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || comp_len == 4 + // Special colorspace + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + + for i in 0..mcu_height { + // Report if we have no more bytes + // This may generate false negatives since we over-read bytes + // hence that why 37 is chosen(we assume if we over-read more than 37 bytes, we have a problem) + if stream.overread_by > 37 + // favourite number :) + { + if self.options.strict_mode() { + return Err(DecodeErrors::FormatStatic("Premature end of buffer")); + }; + + error!("Premature end of buffer"); + break; + } + // decode a whole MCU width, + // this takes into account interleaved components. + self.decode_mcu_width(mcu_width, &mut tmp, &mut stream)?; + // process that width up until it's impossible + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + // it may happen that some images don't have the whole buffer + // so we can't panic in case of that + // assert_eq!(pixels_written, pixels.len()); + + trace!("Finished decoding image"); + + Ok(()) + } + fn decode_mcu_width( + &mut self, mcu_width: usize, tmp: &mut [i32; 64], stream: &mut BitStream + ) -> Result<(), DecodeErrors> { + for j in 0..mcu_width { + // iterate over components + for component in &mut self.components { + let dc_table = self.dc_huffman_tables[component.dc_huff_table % MAX_COMPONENTS] + .as_ref() + .unwrap(); + + let ac_table = self.ac_huffman_tables[component.ac_huff_table % MAX_COMPONENTS] + .as_ref() + .unwrap(); + + let qt_table = &component.quantization_table; + let channel = &mut component.raw_coeff; + + // If image is interleaved iterate over scan components, + // otherwise if it-s non-interleaved, these routines iterate in + // trivial scanline order(Y,Cb,Cr) + for v_samp in 0..component.vertical_sample { + for h_samp in 0..component.horizontal_sample { + // Fill the array with zeroes, decode_mcu_block expects + // a zero based array. + tmp.fill(0); + + stream.decode_mcu_block( + &mut self.stream, + dc_table, + ac_table, + qt_table, + tmp, + &mut component.dc_pred + )?; + + if component.needed { + let idct_position = { + // derived from stb and rewritten for my tastes + let c2 = v_samp * 8; + let c3 = ((j * component.horizontal_sample) + h_samp) * 8; + + component.width_stride * c2 + c3 + }; + + let idct_pos = channel.get_mut(idct_position..).unwrap(); + // call idct. + (self.idct_func)(tmp, idct_pos, component.width_stride); + } + } + } + } + self.todo = self.todo.saturating_sub(1); + // After all interleaved components, that's an MCU + // handle stream markers + // + // In some corrupt images, it may occur that header markers occur in the stream. + // The spec EXPLICITLY FORBIDS this, specifically, in + // routine F.2.2.5 it says + // `The only valid marker which may occur within the Huffman coded data is the RSTm marker.` + // + // But libjpeg-turbo allows it because of some weird reason. so I'll also + // allow it because of some weird reason. + if let Some(m) = stream.marker { + if m == Marker::EOI { + // acknowledge and ignore EOI marker. + stream.marker.take(); + trace!("Found EOI marker"); + // Google Introduced the Ultra-HD image format which is basically + // stitching two images into one container. + // They basically separate two images via a EOI and SOI marker + // so let's just ensure if we ever see EOI, we never read past that + // ever. + // https://github.com/google/libultrahdr + stream.seen_eoi = true; + } else if let Marker::RST(_) = m { + if self.todo == 0 { + self.handle_rst(stream)?; + } + } else { + if self.options.strict_mode() { + return Err(DecodeErrors::Format(format!( + "Marker {m:?} found where not expected" + ))); + } + error!( + "Marker `{:?}` Found within Huffman Stream, possibly corrupt jpeg", + m + ); + + self.parse_marker_inner(m)?; + } + } + } + Ok(()) + } + // handle RST markers. + // No-op if not using restarts + // this routine is shared with mcu_prog + #[cold] + pub(crate) fn handle_rst(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> { + self.todo = self.restart_interval; + + if let Some(marker) = stream.marker { + // Found a marker + // Read stream and see what marker is stored there + match marker { + Marker::RST(_) => { + // reset stream + stream.reset(); + // Initialize dc predictions to zero for all components + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + // Start iterating again. from position. + } + Marker::EOI => { + // silent pass + } + _ => { + return Err(DecodeErrors::MCUError(format!( + "Marker {marker:?} found in bitstream, possibly corrupt jpeg" + ))); + } + } + } + Ok(()) + } + #[allow(clippy::too_many_lines, clippy::too_many_arguments)] + pub(crate) fn post_process( + &mut self, pixels: &mut [u8], i: usize, mcu_height: usize, width: usize, + padded_width: usize, pixels_written: &mut usize, upsampler_scratch_space: &mut [i16] + ) -> Result<(), DecodeErrors> { + let out_colorspace_components = self.options.jpeg_get_out_colorspace().num_components(); + + let mut px = *pixels_written; + // indicates whether image is vertically up-sampled + let is_vertically_sampled = self + .components + .iter() + .any(|c| c.sample_ratio == SampleRatios::HV || c.sample_ratio == SampleRatios::V); + + let mut comp_len = self.components.len(); + + // If we are moving from YCbCr-> Luma, we do not allocate storage for other components, so we + // will panic when we are trying to read samples, so for that case, + // hardcode it so that we don't panic when doing + // *samp = &samples[j][pos * padded_width..(pos + 1) * padded_width] + if out_colorspace_components < comp_len && self.options.jpeg_get_out_colorspace() == Luma { + comp_len = out_colorspace_components; + } + let mut color_conv_function = + |num_iters: usize, samples: [&[i16]; 4]| -> Result<(), DecodeErrors> { + for (pos, output) in pixels[px..] + .chunks_exact_mut(width * out_colorspace_components) + .take(num_iters) + .enumerate() + { + let mut raw_samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + // iterate over each line, since color-convert needs only + // one line + for (j, samp) in raw_samples.iter_mut().enumerate().take(comp_len) { + *samp = &samples[j][pos * padded_width..(pos + 1) * padded_width]; + } + color_convert( + &raw_samples, + self.color_convert_16, + self.input_colorspace, + self.options.jpeg_get_out_colorspace(), + output, + width, + padded_width + )?; + px += width * out_colorspace_components; + } + Ok(()) + }; + + let comps = &mut self.components[..]; + + if self.is_interleaved && self.options.jpeg_get_out_colorspace() != ColorSpace::Luma { + { + // duplicated so that we can check that samples match + // Fixes bug https://github.com/etemesi254/zune-image/issues/151 + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = if component.sample_ratio == SampleRatios::None { + &component.raw_coeff + } else { + &component.upsample_dest + }; + } + } + for comp in comps.iter_mut() { + upsample(comp, mcu_height, i, upsampler_scratch_space); + } + + if is_vertically_sampled { + if i > 0 { + // write the last line, it wasn't up-sampled as we didn't have row_down + // yet + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = &component.first_row_upsample_dest; + } + + // ensure length matches for all samples + let first_len = samples[0].len(); + for samp in samples.iter().take(comp_len) { + assert_eq!(first_len, samp.len()); + } + let num_iters = self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } + + // After upsampling the last row, save any row that can be used for + // a later upsampling, + // + // E.g the Y sample is not sampled but we haven't finished upsampling the last row of + // the previous mcu, since we don't have the down row, so save it + for component in comps.iter_mut() { + // copy last row to be used for the next color conversion + let size = component.vertical_sample + * component.width_stride + * component.sample_ratio.sample(); + + let last_bytes = component.raw_coeff.rchunks_exact_mut(size).next().unwrap(); + + component + .first_row_upsample_dest + .copy_from_slice(last_bytes); + } + } + + let mut samples: [&[i16]; 4] = [&[], &[], &[], &[]]; + + for (samp, component) in samples.iter_mut().zip(comps.iter()) { + *samp = if component.sample_ratio == SampleRatios::None { + &component.raw_coeff + } else { + &component.upsample_dest + }; + } + + // we either do 7 or 8 MCU's depending on the state, this only applies to + // vertically sampled images + // + // for rows up until the last MCU, we do not upsample the last stride of the MCU + // which means that the number of iterations should take that into account is one less the + // up-sampled size + // + // For the last MCU, we upsample the last stride, meaning that if we hit the last MCU, we + // should sample full raw coeffs + let is_last_considered = is_vertically_sampled && (i != mcu_height.saturating_sub(1)); + + let num_iters = (8 - usize::from(is_last_considered)) * self.coeff * self.v_max; + + color_conv_function(num_iters, samples)?; + } else { + let mut channels_ref: [&[i16]; MAX_COMPONENTS] = [&[]; MAX_COMPONENTS]; + + self.components + .iter() + .enumerate() + .for_each(|(pos, x)| channels_ref[pos] = &x.raw_coeff); + + color_conv_function(8 * self.coeff, channels_ref)?; + } + + *pixels_written = px; + Ok(()) + } +} +// #[cfg(test)] +// mod tests { +// use zune_core::bytestream::ZCursor; +// +// use crate::JpegDecoder; +// +// #[test] +// fn im() { +// let image = std::fs::read("/home/caleb/Downloads/re.jpg").unwrap(); +// JpegDecoder::new(ZCursor::new(&image)).decode().unwrap(); +// } +// } diff --git a/third_party/zune-jpeg/src/mcu_prog.rs b/third_party/zune-jpeg/src/mcu_prog.rs new file mode 100644 index 0000000..ce309a6 --- /dev/null +++ b/third_party/zune-jpeg/src/mcu_prog.rs @@ -0,0 +1,617 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Routines for progressive decoding +/* +This file is needlessly complicated, + +It is that way to ensure we don't burn memory anyhow + +Memory is a scarce resource in some environments, I would like this to be viable +in such environments + +Half of the complexity comes from the jpeg spec, because progressive decoding, +is one hell of a ride. + +*/ +use alloc::string::ToString; +use alloc::vec::Vec; +use alloc::{format, vec}; +use core::cmp::min; + +use zune_core::bytestream::{ZByteReaderTrait, ZReader}; +use zune_core::colorspace::ColorSpace; +use zune_core::log::{debug, error, warn}; + +use crate::bitstream::BitStream; +use crate::components::{ComponentID, SampleRatios}; +use crate::decoder::{JpegDecoder, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; +use crate::errors::DecodeErrors::Format; +use crate::headers::{parse_huffman, parse_sos}; +use crate::marker::Marker; +use crate::mcu::DCT_BLOCK; +use crate::misc::{calculate_padded_width, setup_component_params}; + +impl JpegDecoder { + /// Decode a progressive image + /// + /// This routine decodes a progressive image, stopping if it finds any error. + #[allow( + clippy::needless_range_loop, + clippy::cast_sign_loss, + clippy::redundant_else, + clippy::too_many_lines + )] + #[inline(never)] + pub(crate) fn decode_mcu_ycbcr_progressive( + &mut self, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + setup_component_params(self)?; + + let mut mcu_height; + + // memory location for decoded pixels for components + let mut block: [Vec; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]]; + let mut mcu_width; + + let mut seen_scans = 1; + + if self.input_colorspace == ColorSpace::Luma && self.is_interleaved { + warn!("Grayscale image with down-sampled component, resetting component details"); + self.reset_params(); + } + + if self.is_interleaved { + // this helps us catch component errors. + self.set_upsampling()?; + } + if self.is_interleaved { + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } else { + mcu_width = (self.info.width as usize + 7) / 8; + mcu_height = (self.info.height as usize + 7) / 8; + } + if self.is_interleaved + && self.input_colorspace.num_components() > 1 + && self.options.jpeg_get_out_colorspace().num_components() == 1 + && (self.sub_sample_ratio == SampleRatios::V + || self.sub_sample_ratio == SampleRatios::HV) + { + // For a specific set of images, e.g interleaved, + // when converting from YcbCr to grayscale, we need to + // take into account mcu height since the MCU decoding needs to take + // it into account for padding purposes and the post processor + // parses two rows per mcu width. + // + // set coeff to be 2 to ensure that we increment two rows + // for every mcu processed also + mcu_height *= self.v_max; + mcu_height /= self.h_max; + self.coeff = 2; + } + + mcu_width *= 64; + + if self.input_colorspace.num_components() > self.components.len() { + let msg = format!( + " Expected {} number of components but found {}", + self.input_colorspace.num_components(), + self.components.len() + ); + return Err(DecodeErrors::Format(msg)); + } + for i in 0..self.input_colorspace.num_components() { + let comp = &self.components[i]; + let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height; + + block[i] = vec![0; len]; + } + + let mut stream = BitStream::new_progressive( + self.succ_high, + self.succ_low, + self.spec_start, + self.spec_end + ); + + // there are multiple scans in the stream, this should resolve the first scan + self.parse_entropy_coded_data(&mut stream, &mut block)?; + + // extract marker + let mut marker = stream + .marker + .take() + .ok_or(DecodeErrors::FormatStatic("Marker missing where expected"))?; + + // if marker is EOI, we are done, otherwise continue scanning. + // + // In case we have a premature image, we print a warning or return + // an error, depending on the strictness of the decoder, so there + // is that logic to handle too + 'eoi: while marker != Marker::EOI { + match marker { + Marker::DHT => { + parse_huffman(self)?; + } + Marker::SOS => { + parse_sos(self)?; + + stream.update_progressive_params( + self.succ_high, + self.succ_low, + self.spec_start, + self.spec_end + ); + + // after every SOS, marker, parse data for that scan. + self.parse_entropy_coded_data(&mut stream, &mut block)?; + // extract marker, might either indicate end of image or we continue + // scanning(hence the continue statement to determine). + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + seen_scans += 1; + if seen_scans > self.options.jpeg_get_max_scans() { + return Err(DecodeErrors::Format(format!( + "Too many scans, exceeded limit of {}", + self.options.jpeg_get_max_scans() + ))); + } + + stream.reset(); + continue 'eoi; + } + Err(msg) => { + if self.options.strict_mode() { + return Err(msg); + } + error!("{:?}", msg); + break 'eoi; + } + } + } + _ => { + break 'eoi; + } + } + + match get_marker(&mut self.stream, &mut stream) { + Ok(marker_n) => { + marker = marker_n; + } + Err(e) => { + if self.options.strict_mode() { + return Err(e); + } + error!("{}", e); + } + } + } + + self.finish_progressive_decoding(&block, mcu_width, pixels) + } + + #[allow(clippy::too_many_lines, clippy::cast_sign_loss)] + fn parse_entropy_coded_data( + &mut self, stream: &mut BitStream, buffer: &mut [Vec; MAX_COMPONENTS] + ) -> Result<(), DecodeErrors> { + stream.reset(); + self.components.iter_mut().for_each(|x| x.dc_pred = 0); + + if usize::from(self.num_scans) > self.input_colorspace.num_components() { + return Err(Format(format!( + "Number of scans {} cannot be greater than number of components, {}", + self.num_scans, + self.input_colorspace.num_components() + ))); + } + + if self.num_scans == 1 { + // Safety checks + if self.spec_end != 0 && self.spec_start == 0 { + return Err(DecodeErrors::FormatStatic( + "Can't merge DC and AC corrupt jpeg" + )); + } + // non interleaved data, process one block at a time in trivial scanline order + + let k = self.z_order[0]; + + if k >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {k}, corrupt image" + ))); + } + + let (mcu_width, mcu_height); + + if self.components[k].component_id == ComponentID::Y + && (self.components[k].vertical_sample != 1 + || self.components[k].horizontal_sample != 1) + || !self.is_interleaved + { + // For Y channel or non interleaved scans , + // mcu's is the image dimensions divided by 8 + mcu_width = ((self.info.width + 7) / 8) as usize; + mcu_height = ((self.info.height + 7) / 8) as usize; + } else { + // For other channels, in an interleaved mcu, number of MCU's + // are determined by some weird maths done in headers.rs->parse_sos() + mcu_width = self.mcu_x; + mcu_height = self.mcu_y; + } + + for i in 0..mcu_height { + for j in 0..mcu_width { + if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 { + // handle EOB runs here. + stream.eob_run -= 1; + continue; + } + let start = 64 * (j + i * (self.components[k].width_stride / 8)); + + let data: &mut [i16; 64] = buffer + .get_mut(k) + .unwrap() + .get_mut(start..start + 64) + .unwrap() + .try_into() + .unwrap(); + + if self.spec_start == 0 { + let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1); + let dc_table = self + .dc_huffman_tables + .get(pos) + .ok_or(DecodeErrors::FormatStatic( + "No huffman table for DC component" + ))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index {} not initialized" + ))?; + + let dc_pred = &mut self.components[k].dc_pred; + + if self.succ_high == 0 { + // first scan for this mcu + stream.decode_prog_dc_first( + &mut self.stream, + dc_table, + &mut data[0], + dc_pred + )?; + } else { + // refining scans for this MCU + stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?; + } + } else { + let pos = self.components[k].ac_huff_table; + let ac_table = self + .ac_huffman_tables + .get(pos) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{pos}" + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {pos} not initialized" + )) + })?; + + if self.succ_high == 0 { + debug_assert!(stream.eob_run == 0, "EOB run is not zero"); + + stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?; + } else { + // refinement scan + stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?; + } + } + // + EOB and investigate effect. + self.todo -= 1; + + if self.todo == 0 { + self.handle_rst(stream)?; + } + } + } + } else { + if self.spec_end != 0 { + return Err(DecodeErrors::HuffmanDecode( + "Can't merge dc and AC corrupt jpeg".to_string() + )); + } + // process scan n elements in order + + // Do the error checking with allocs here. + // Make the one in the inner loop free of allocations. + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + + if n >= self.components.len() { + return Err(DecodeErrors::Format(format!( + "Cannot find component {n}, corrupt image" + ))); + } + + let component = &mut self.components[n]; + let _ = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or_else(|| { + DecodeErrors::Format(format!( + "No huffman table for component:{}", + component.dc_huff_table + )) + })? + .as_ref() + .ok_or_else(|| { + DecodeErrors::Format(format!( + "Huffman table at index {} not initialized", + component.dc_huff_table + )) + })?; + } + // Interleaved scan + + // Components shall not be interleaved in progressive mode, except for + // the DC coefficients in the first scan for each component of a progressive frame. + for i in 0..self.mcu_y { + for j in 0..self.mcu_x { + // process scan n elements in order + for k in 0..self.num_scans { + let n = self.z_order[k as usize]; + let component = &mut self.components[n]; + let huff_table = self + .dc_huffman_tables + .get(component.dc_huff_table) + .ok_or(DecodeErrors::FormatStatic("No huffman table for component"))? + .as_ref() + .ok_or(DecodeErrors::FormatStatic( + "Huffman table at index not initialized" + ))?; + + for v_samp in 0..component.vertical_sample { + for h_samp in 0..component.horizontal_sample { + let x2 = j * component.horizontal_sample + h_samp; + let y2 = i * component.vertical_sample + v_samp; + let position = 64 * (x2 + y2 * component.width_stride / 8); + + let data = &mut buffer[n][position]; + + if self.succ_high == 0 { + stream.decode_prog_dc_first( + &mut self.stream, + huff_table, + data, + &mut component.dc_pred + )?; + } else { + stream.decode_prog_dc_refine(&mut self.stream, data)?; + } + } + } + } + // We want wrapping subtraction here because it means + // we get a higher number in the case this underflows + self.todo = self.todo.wrapping_sub(1); + // after every scan that's a mcu, count down restart markers. + if self.todo == 0 { + self.handle_rst(stream)?; + } + } + } + } + return Ok(()); + } + + #[allow(clippy::too_many_lines)] + #[allow(clippy::needless_range_loop, clippy::cast_sign_loss)] + fn finish_progressive_decoding( + &mut self, block: &[Vec; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8] + ) -> Result<(), DecodeErrors> { + // This function is complicated because we need to replicate + // the function in mcu.rs + // + // The advantage is that we do very little allocation and very lot + // channel reusing. + // The trick is to notice that we repeat the same procedure per MCU + // width. + // + // So we can set it up that we only allocate temporary storage large enough + // to store a single mcu width, then reuse it per invocation. + // + // This is advantageous to us. + // + // Remember we need to have the whole MCU buffer so we store 3 unprocessed + // channels in memory, and then we allocate the whole output buffer in memory, both of + // which are huge. + // + // + + let mcu_height = if self.is_interleaved { + self.mcu_y + } else { + // For non-interleaved images( (1*1) subsampling) + // number of MCU's are the widths (+7 to account for paddings) divided by 8. + ((self.info.height + 7) / 8) as usize + }; + + // Size of our output image(width*height) + let is_hv = usize::from(self.is_interleaved); + let upsampler_scratch_size = is_hv * self.components[0].width_stride; + let width = usize::from(self.info.width); + let padded_width = calculate_padded_width(width, self.sub_sample_ratio); + + //let mut pixels = vec![0; capacity * out_colorspace_components]; + let mut upsampler_scratch_space = vec![0; upsampler_scratch_size]; + let mut tmp = [0_i32; DCT_BLOCK]; + + for (pos, comp) in self.components.iter_mut().enumerate() { + // Allocate only needed components. + // + // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed + // components. + if min( + self.options.jpeg_get_out_colorspace().num_components() - 1, + pos + ) == pos + || self.input_colorspace == ColorSpace::YCCK + || self.input_colorspace == ColorSpace::CMYK + { + // allocate enough space to hold a whole MCU width + // this means we should take into account sampling ratios + // `*8` is because each MCU spans 8 widths. + let len = comp.width_stride * comp.vertical_sample * 8; + + comp.needed = true; + comp.raw_coeff = vec![0; len]; + } else { + comp.needed = false; + } + } + + let mut pixels_written = 0; + + // dequantize, idct and color convert. + for i in 0..mcu_height { + 'component: for (position, component) in &mut self.components.iter_mut().enumerate() { + if !component.needed { + continue 'component; + } + let qt_table = &component.quantization_table; + + // step is the number of pixels this iteration wil be handling + // Given by the number of mcu's height and the length of the component block + // Since the component block contains the whole channel as raw pixels + // we this evenly divides the pixels into MCU blocks + // + // For interleaved images, this gives us the exact pixels comprising a whole MCU + // block + let step = block[position].len() / mcu_height; + // where we will be reading our pixels from. + let start = i * step; + + let slice = &block[position][start..start + step]; + + let temp_channel = &mut component.raw_coeff; + + // The next logical step is to iterate width wise. + // To figure out how many pixels we iterate by we use effective pixels + // Given to us by component.x + // iterate per effective pixels. + let mcu_x = component.width_stride / 8; + + // iterate per every vertical sample. + for k in 0..component.vertical_sample { + for j in 0..mcu_x { + // after writing a single stride, we need to skip 8 rows. + // This does the row calculation + let width_stride = k * 8 * component.width_stride; + let start = j * 64 + width_stride; + + // dequantize + for ((x, out), qt_val) in slice[start..start + 64] + .iter() + .zip(tmp.iter_mut()) + .zip(qt_table.iter()) + { + *out = i32::from(*x) * qt_val; + } + // determine where to write. + let sl = &mut temp_channel[component.idct_pos..]; + + component.idct_pos += 8; + // tmp now contains a dequantized block so idct it + (self.idct_func)(&mut tmp, sl, component.width_stride); + } + // after every write of 8, skip 7 since idct write stride wise 8 times. + // + // Remember each MCU is 8x8 block, so each idct will write 8 strides into + // sl + // + // and component.idct_pos is one stride long + component.idct_pos += 7 * component.width_stride; + } + component.idct_pos = 0; + } + + // process that width up until it's impossible + self.post_process( + pixels, + i, + mcu_height, + width, + padded_width, + &mut pixels_written, + &mut upsampler_scratch_space + )?; + } + + debug!("Finished decoding image"); + + return Ok(()); + } + pub(crate) fn reset_params(&mut self) { + /* + Apparently, grayscale images which can be down sampled exists, which is weird in the sense + that it has one component Y, which is not usually down sampled. + + This means some calculations will be wrong, so for that we explicitly reset params + for such occurrences, warn and reset the image info to appear as if it were + a non-sampled image to ensure decoding works + */ + self.h_max = 1; + self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma); + self.v_max = 1; + self.sub_sample_ratio = SampleRatios::None; + self.is_interleaved = false; + self.components[0].vertical_sample = 1; + self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8; + self.components[0].horizontal_sample = 1; + } +} + +///Get a marker from the bit-stream. +/// +/// This reads until it gets a marker or end of file is encountered +fn get_marker(reader: &mut ZReader, stream: &mut BitStream) -> Result +where + T: ZByteReaderTrait +{ + if let Some(marker) = stream.marker { + stream.marker = None; + return Ok(marker); + } + + // read until we get a marker + + while !reader.eof()? { + let marker = reader.read_u8_err()?; + + if marker == 255 { + let mut r = reader.read_u8_err()?; + // 0xFF 0XFF(some images may be like that) + while r == 0xFF { + r = reader.read_u8_err()?; + } + + if r != 0 { + return Marker::from_u8(r) + .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}"))); + } + } + } + return Err(DecodeErrors::ExhaustedData); +} diff --git a/third_party/zune-jpeg/src/misc.rs b/third_party/zune-jpeg/src/misc.rs new file mode 100644 index 0000000..1c180b3 --- /dev/null +++ b/third_party/zune-jpeg/src/misc.rs @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//!Miscellaneous stuff +#![allow(dead_code)] + +use alloc::format; +use core::cmp::max; +use core::fmt; + +use zune_core::bytestream::ZByteReaderTrait; +use zune_core::colorspace::ColorSpace; +use zune_core::log::trace; + +use crate::components::{ComponentID, SampleRatios}; +use crate::errors::DecodeErrors; +use crate::huffman::HuffmanTable; +use crate::JpegDecoder; + +/// Start of baseline DCT Huffman coding + +pub const START_OF_FRAME_BASE: u16 = 0xffc0; + +/// Start of another frame + +pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1; + +/// Start of progressive DCT encoding + +pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2; + +/// Start of Lossless sequential Huffman coding + +pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3; + +/// Start of extended sequential DCT arithmetic coding + +pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9; + +/// Start of Progressive DCT arithmetic coding + +pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca; + +/// Start of Lossless sequential Arithmetic coding + +pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb; + +/// Undo run length encoding of coefficients by placing them in natural order +#[rustfmt::skip] +pub const UN_ZIGZAG: [usize; 64 + 16] = [ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // Prevent overflowing + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 +]; + +/// Align data to a 16 byte boundary +#[repr(align(16))] +#[derive(Clone)] + +pub struct Aligned16(pub T); + +impl Default for Aligned16 +where + T: Default +{ + fn default() -> Self { + Aligned16(T::default()) + } +} + +/// Align data to a 32 byte boundary +#[repr(align(32))] +#[derive(Clone)] +pub struct Aligned32(pub T); + +impl Default for Aligned32 +where + T: Default +{ + fn default() -> Self { + Aligned32(T::default()) + } +} + +/// Markers that identify different Start of Image markers +/// They identify the type of encoding and whether the file use lossy(DCT) or +/// lossless compression and whether we use Huffman or arithmetic coding schemes +#[derive(Eq, PartialEq, Copy, Clone)] +#[allow(clippy::upper_case_acronyms)] +pub enum SOFMarkers { + /// Baseline DCT markers + BaselineDct, + /// SOF_1 Extended sequential DCT,Huffman coding + ExtendedSequentialHuffman, + /// Progressive DCT, Huffman coding + ProgressiveDctHuffman, + /// Lossless (sequential), huffman coding, + LosslessHuffman, + /// Extended sequential DEC, arithmetic coding + ExtendedSequentialDctArithmetic, + /// Progressive DCT, arithmetic coding, + ProgressiveDctArithmetic, + /// Lossless ( sequential), arithmetic coding + LosslessArithmetic +} + +impl Default for SOFMarkers { + fn default() -> Self { + Self::BaselineDct + } +} + +impl SOFMarkers { + /// Check if a certain marker is sequential DCT or not + + pub fn is_sequential_dct(self) -> bool { + matches!( + self, + Self::BaselineDct + | Self::ExtendedSequentialHuffman + | Self::ExtendedSequentialDctArithmetic + ) + } + + /// Check if a marker is a Lossles type or not + + pub fn is_lossless(self) -> bool { + matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic) + } + + /// Check whether a marker is a progressive marker or not + + pub fn is_progressive(self) -> bool { + matches!( + self, + Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic + ) + } + + /// Create a marker from an integer + + pub fn from_int(int: u16) -> Option { + match int { + START_OF_FRAME_BASE => Some(Self::BaselineDct), + START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman), + START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic), + START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman), + START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic), + START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman), + START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic), + _ => None + } + } +} + +impl fmt::Debug for SOFMarkers { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self { + Self::BaselineDct => write!(f, "Baseline DCT"), + Self::ExtendedSequentialHuffman => { + write!(f, "Extended sequential DCT, Huffman Coding") + } + Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"), + Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"), + Self::ExtendedSequentialDctArithmetic => { + write!(f, "Extended sequential DCT, arithmetic coding") + } + Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"), + Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding") + } + } +} + +/// Set up component parameters. +/// +/// This modifies the components in place setting up details needed by other +/// parts fo the decoder. +pub(crate) fn setup_component_params( + img: &mut JpegDecoder +) -> Result<(), DecodeErrors> { + let img_width = img.width(); + let img_height = img.height(); + + // in case of adobe app14 being present, zero may indicate + // either CMYK if components are 4 or RGB if components are 3, + // see https://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html + // so since we may not know how many number of components + // we have when decoding app14, we have to defer that check + // until now. + // + // We know adobe app14 was present since it's the only one that can modify + // input colorspace to be CMYK + if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK { + img.input_colorspace = ColorSpace::RGB; + } + + for component in &mut img.components { + // compute interleaved image info + // h_max contains the maximum horizontal component + img.h_max = max(img.h_max, component.horizontal_sample); + // v_max contains the maximum vertical component + img.v_max = max(img.v_max, component.vertical_sample); + img.mcu_width = img.h_max * 8; + img.mcu_height = img.v_max * 8; + // Number of MCU's per width + img.mcu_x = (usize::from(img.info.width) + img.mcu_width - 1) / img.mcu_width; + // Number of MCU's per height + img.mcu_y = (usize::from(img.info.height) + img.mcu_height - 1) / img.mcu_height; + + if img.h_max != 1 || img.v_max != 1 { + // interleaved images have horizontal and vertical sampling factors + // not equal to 1. + img.is_interleaved = true; + } + // Extract quantization tables from the arrays into components + let qt_table = *img.qt_tables[component.quantization_table_number as usize] + .as_ref() + .ok_or_else(|| { + DecodeErrors::DqtError(format!( + "No quantization table for component {:?}", + component.component_id + )) + })?; + + let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max; + let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max; + component.x = x; + component.w2 = img.mcu_x * component.horizontal_sample * 8; + // probably not needed. :) + component.y = y; + component.quantization_table = qt_table; + // initially stride contains its horizontal sub-sampling + component.width_stride *= img.mcu_x * 8; + } + { + // Sampling factors are one thing that suck + // this fixes a specific problem with images like + // + // (2 2) None + // (2 1) H + // (2 1) H + // + // The images exist in the wild, the images are not meant to exist + // but they do, it's just an annoying horizontal sub-sampling that + // I don't know why it exists. + // But it does + // So we try to cope with that. + // I am not sure of how to explain how to fix it, but it involved a debugger + // and to much coke(the legal one) + // + // If this wasn't present, self.upsample_dest would have the wrong length + let mut handle_that_annoying_bug = false; + + if let Some(y_component) = img + .components + .iter() + .find(|c| c.component_id == ComponentID::Y) + { + if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 { + handle_that_annoying_bug = true; + } + } + if handle_that_annoying_bug { + for comp in &mut img.components { + if (comp.component_id != ComponentID::Y) + && (comp.horizontal_sample != 1 || comp.vertical_sample != 1) + { + comp.fix_an_annoying_bug = 2; + } + } + } + } + + if img.is_mjpeg { + fill_default_mjpeg_tables( + img.is_progressive, + &mut img.dc_huffman_tables, + &mut img.ac_huffman_tables + ); + } + + Ok(()) +} + +///Calculate number of fill bytes added to the end of a JPEG image +/// to fill the image +/// +/// JPEG usually inserts padding bytes if the image width cannot be evenly divided into +/// 8 , 16 or 32 chunks depending on the sub sampling ratio. So given a sub-sampling ratio, +/// and the actual width, this calculates the padded bytes that were added to the image +/// +/// # Params +/// -actual_width: Actual width of the image +/// -sub_sample: Sub sampling factor of the image +/// +/// # Returns +/// The padded width, this is how long the width is for a particular image +pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize { + match sub_sample { + SampleRatios::None | SampleRatios::V => { + // None+V sends one MCU row, so that's a simple calculation + ((actual_width + 7) / 8) * 8 + } + SampleRatios::H | SampleRatios::HV => { + // sends two rows, width can be expanded by up to 15 more bytes + ((actual_width + 15) / 16) * 16 + } + } +} + +// https://www.loc.gov/preservation/digital/formats/fdd/fdd000063.shtml +// "Avery Lee, writing in the rec.video.desktop newsgroup in 2001, commented that "MJPEG, or at +// least the MJPEG in AVIs having the MJPG fourcc, is restricted JPEG with a fixed -- and +// *omitted* -- Huffman table. The JPEG must be YCbCr colorspace, it must be 4:2:2, and it must +// use basic Huffman encoding, not arithmetic or progressive.... You can indeed extract the +// MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT +// segment to them, or else the decoder won't have any idea how to decompress the data. +// The exact table necessary is given in the OpenDML spec."" +pub fn fill_default_mjpeg_tables( + is_progressive: bool, dc_huffman_tables: &mut [Option], + ac_huffman_tables: &mut [Option] +) { + // Section K.3.3 + trace!("Filling with default mjpeg tables"); + + if dc_huffman_tables[0].is_none() { + // Table K.3 + dc_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if dc_huffman_tables[1].is_none() { + // Table K.4 + dc_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B + ], + true, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[0].is_none() { + // Table K.5 + ac_huffman_tables[0] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, + 0x00, 0x00, 0x01, 0x7D + ], + &[ + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, + 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, + 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } + if ac_huffman_tables[1].is_none() { + // Table K.6 + ac_huffman_tables[1] = Some( + HuffmanTable::new_unfilled( + &[ + 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, + 0x00, 0x01, 0x02, 0x77 + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, + 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, + 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, + 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA + ], + false, + is_progressive + ) + .unwrap() + ); + } +} diff --git a/third_party/zune-jpeg/src/unsafe_utils.rs b/third_party/zune-jpeg/src/unsafe_utils.rs new file mode 100644 index 0000000..325ebbe --- /dev/null +++ b/third_party/zune-jpeg/src/unsafe_utils.rs @@ -0,0 +1,4 @@ +#[cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +pub use crate::unsafe_utils_avx2::*; +#[cfg(all(feature = "neon", target_arch = "aarch64"))] +pub use crate::unsafe_utils_neon::*; diff --git a/third_party/zune-jpeg/src/unsafe_utils_avx2.rs b/third_party/zune-jpeg/src/unsafe_utils_avx2.rs new file mode 100644 index 0000000..eb34b63 --- /dev/null +++ b/third_party/zune-jpeg/src/unsafe_utils_avx2.rs @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(all(feature = "x86", any(target_arch = "x86", target_arch = "x86_64")))] +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub}; + +/// A copy of `_MM_SHUFFLE()` that doesn't require +/// a nightly compiler +#[inline] +const fn shuffle(z: i32, y: i32, x: i32, w: i32) -> i32 { + (z << 6) | (y << 4) | (x << 2) | w +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: __m256i +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl Add for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + return YmmRegister { + mm256: _mm256_add_epi32(self.mm256, tmp) + }; + } + } +} + +impl Sub for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + unsafe { + return YmmRegister { + mm256: _mm256_sub_epi32(self.mm256, rhs.mm256) + }; + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_add_epi32(self.mm256, rhs.mm256); + } + } +} + +impl AddAssign for YmmRegister { + #[inline] + fn add_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_add_epi32(self.mm256, tmp); + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + unsafe { + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, rhs.mm256) + } + } + } +} + +impl Mul for YmmRegister { + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: i32) -> Self::Output { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + YmmRegister { + mm256: _mm256_mullo_epi32(self.mm256, tmp) + } + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: Self) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs.mm256); + } + } +} + +impl MulAssign for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: i32) { + unsafe { + let tmp = _mm256_set1_epi32(rhs); + + self.mm256 = _mm256_mullo_epi32(self.mm256, tmp); + } + } +} + +impl MulAssign<__m256i> for YmmRegister { + #[inline] + fn mul_assign(&mut self, rhs: __m256i) { + unsafe { + self.mm256 = _mm256_mullo_epi32(self.mm256, rhs); + } + } +} + +type Reg = YmmRegister; + +/// Transpose an array of 8 by 8 i32's using avx intrinsics +/// +/// This was translated from [here](https://newbedev.com/transpose-an-8x8-float-using-avx-avx2) +#[allow(unused_parens, clippy::too_many_arguments)] +#[target_feature(enable = "avx2")] +#[inline] +pub unsafe fn transpose( + v0: &mut Reg, v1: &mut Reg, v2: &mut Reg, v3: &mut Reg, v4: &mut Reg, v5: &mut Reg, + v6: &mut Reg, v7: &mut Reg +) { + macro_rules! merge_epi32 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi32(va, vb); + + $v3 = _mm256_unpackhi_epi32(va, vb); + }; + } + + macro_rules! merge_epi64 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + let va = _mm256_permute4x64_epi64($v0, shuffle(3, 1, 2, 0)); + + let vb = _mm256_permute4x64_epi64($v1, shuffle(3, 1, 2, 0)); + + $v2 = _mm256_unpacklo_epi64(va, vb); + + $v3 = _mm256_unpackhi_epi64(va, vb); + }; + } + + macro_rules! merge_si128 { + ($v0:tt,$v1:tt,$v2:tt,$v3:tt) => { + $v2 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 2, 0, 0)); + + $v3 = _mm256_permute2x128_si256($v0, $v1, shuffle(0, 3, 0, 1)); + }; + } + + let (w0, w1, w2, w3, w4, w5, w6, w7); + + merge_epi32!((v0.mm256), (v1.mm256), w0, w1); + + merge_epi32!((v2.mm256), (v3.mm256), w2, w3); + + merge_epi32!((v4.mm256), (v5.mm256), w4, w5); + + merge_epi32!((v6.mm256), (v7.mm256), w6, w7); + + let (x0, x1, x2, x3, x4, x5, x6, x7); + + merge_epi64!(w0, w2, x0, x1); + + merge_epi64!(w1, w3, x2, x3); + + merge_epi64!(w4, w6, x4, x5); + + merge_epi64!(w5, w7, x6, x7); + + merge_si128!(x0, x4, (v0.mm256), (v1.mm256)); + + merge_si128!(x1, x5, (v2.mm256), (v3.mm256)); + + merge_si128!(x2, x6, (v4.mm256), (v5.mm256)); + + merge_si128!(x3, x7, (v6.mm256), (v7.mm256)); +} diff --git a/third_party/zune-jpeg/src/unsafe_utils_neon.rs b/third_party/zune-jpeg/src/unsafe_utils_neon.rs new file mode 100644 index 0000000..78b32f9 --- /dev/null +++ b/third_party/zune-jpeg/src/unsafe_utils_neon.rs @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +#![cfg(target_arch = "aarch64")] +// TODO can this be extended to armv7 + +//! This module provides unsafe ways to do some things +#![allow(clippy::wildcard_imports)] + +use std::arch::aarch64::*; +use std::ops::{Add, AddAssign, BitOr, BitOrAssign, Mul, MulAssign, Sub}; + +pub type VecType = int32x4x2_t; + +pub unsafe fn loadu(src: *const i32) -> VecType { + vld1q_s32_x2(src as *const _) +} + +/// An abstraction of an AVX ymm register that +///allows some things to not look ugly +#[derive(Clone, Copy)] +pub struct YmmRegister { + /// An AVX register + pub(crate) mm256: VecType +} + +impl YmmRegister { + #[inline] + pub unsafe fn load(src: *const i32) -> Self { + loadu(src).into() + } + + #[inline] + pub fn map2(self, other: Self, f: impl Fn(int32x4_t, int32x4_t) -> int32x4_t) -> Self { + let m0 = f(self.mm256.0, other.mm256.0); + let m1 = f(self.mm256.1, other.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + + #[inline] + pub fn all_zero(self) -> bool { + unsafe { + let both = vorrq_s32(self.mm256.0, self.mm256.1); + let both_unsigned = vreinterpretq_u32_s32(both); + 0 == vmaxvq_u32(both_unsigned) + } + } + + #[inline] + pub fn const_shl(self) -> Self { + // Ensure that we logically shift left + unsafe { + let m0 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.0))); + let m1 = vreinterpretq_s32_u32(vshlq_n_u32::(vreinterpretq_u32_s32(self.mm256.1))); + + YmmRegister { + mm256: int32x4x2_t(m0, m1) + } + } + } + + #[inline] + pub fn const_shra(self) -> Self { + unsafe { + let i0 = vshrq_n_s32::(self.mm256.0); + let i1 = vshrq_n_s32::(self.mm256.1); + + YmmRegister { + mm256: int32x4x2_t(i0, i1) + } + } + } +} + +impl Add for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn add(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vaddq_s32(a, b)) } + } +} + +impl Sub for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn sub(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vsubq_s32(a, b)) } + } +} + +impl AddAssign for YmmRegister +where + T: Into +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self + rhs; + } +} + +impl Mul for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn mul(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vmulq_s32(a, b)) } + } +} + +impl MulAssign for YmmRegister +where + T: Into +{ + #[inline] + fn mul_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self * rhs; + } +} + +impl BitOr for YmmRegister +where + T: Into +{ + type Output = YmmRegister; + + #[inline] + fn bitor(self, rhs: T) -> Self::Output { + let rhs = rhs.into(); + unsafe { self.map2(rhs, |a, b| vorrq_s32(a, b)) } + } +} + +impl BitOrAssign for YmmRegister +where + T: Into +{ + #[inline] + fn bitor_assign(&mut self, rhs: T) { + let rhs: Self = rhs.into(); + *self = *self | rhs; + } +} + +impl From for YmmRegister { + #[inline] + fn from(val: i32) -> Self { + unsafe { + let dup = vdupq_n_s32(val); + + YmmRegister { + mm256: int32x4x2_t(dup, dup) + } + } + } +} + +impl From for YmmRegister { + #[inline] + fn from(mm256: VecType) -> Self { + YmmRegister { mm256 } + } +} + +#[allow(clippy::too_many_arguments)] +#[inline] +unsafe fn transpose4( + v0: &mut int32x4_t, v1: &mut int32x4_t, v2: &mut int32x4_t, v3: &mut int32x4_t +) { + let w0 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn1q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + let w1 = vtrnq_s32( + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v0), + vreinterpretq_s64_s32(*v2) + )), + vreinterpretq_s32_s64(vtrn2q_s64( + vreinterpretq_s64_s32(*v1), + vreinterpretq_s64_s32(*v3) + )) + ); + + *v0 = w0.0; + *v1 = w0.1; + *v2 = w1.0; + *v3 = w1.1; +} + +/// Transpose an array of 8 by 8 i32 +/// Arm has dedicated interleave/transpose instructions +/// we: +/// 1. Transpose the upper left and lower right quadrants +/// 2. Swap and transpose the upper right and lower left quadrants +#[allow(clippy::too_many_arguments)] +#[inline] +pub unsafe fn transpose( + v0: &mut YmmRegister, v1: &mut YmmRegister, v2: &mut YmmRegister, v3: &mut YmmRegister, + v4: &mut YmmRegister, v5: &mut YmmRegister, v6: &mut YmmRegister, v7: &mut YmmRegister +) { + use std::mem::swap; + + let ul0 = &mut v0.mm256.0; + let ul1 = &mut v1.mm256.0; + let ul2 = &mut v2.mm256.0; + let ul3 = &mut v3.mm256.0; + + let ur0 = &mut v0.mm256.1; + let ur1 = &mut v1.mm256.1; + let ur2 = &mut v2.mm256.1; + let ur3 = &mut v3.mm256.1; + + let ll0 = &mut v4.mm256.0; + let ll1 = &mut v5.mm256.0; + let ll2 = &mut v6.mm256.0; + let ll3 = &mut v7.mm256.0; + + let lr0 = &mut v4.mm256.1; + let lr1 = &mut v5.mm256.1; + let lr2 = &mut v6.mm256.1; + let lr3 = &mut v7.mm256.1; + + swap(ur0, ll0); + swap(ur1, ll1); + swap(ur2, ll2); + swap(ur3, ll3); + + transpose4(ul0, ul1, ul2, ul3); + + transpose4(ur0, ur1, ur2, ur3); + + transpose4(ll0, ll1, ll2, ll3); + + transpose4(lr0, lr1, lr2, lr3); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_transpose() { + fn get_val(i: usize, j: usize) -> i32 { + ((i * 8) / (j + 1)) as i32 + } + unsafe { + let mut vals: [i32; 8 * 8] = [0; 8 * 8]; + + for i in 0..8 { + for j in 0..8 { + // some order-dependent value of i and j + let value = get_val(i, j); + vals[i * 8 + j] = value; + } + } + + let mut regs: [YmmRegister; 8] = std::mem::transmute(vals); + let mut reg0 = regs[0]; + let mut reg1 = regs[1]; + let mut reg2 = regs[2]; + let mut reg3 = regs[3]; + let mut reg4 = regs[4]; + let mut reg5 = regs[5]; + let mut reg6 = regs[6]; + let mut reg7 = regs[7]; + + transpose( + &mut reg0, &mut reg1, &mut reg2, &mut reg3, &mut reg4, &mut reg5, &mut reg6, + &mut reg7 + ); + + regs[0] = reg0; + regs[1] = reg1; + regs[2] = reg2; + regs[3] = reg3; + regs[4] = reg4; + regs[5] = reg5; + regs[6] = reg6; + regs[7] = reg7; + + let vals_from_reg: [i32; 8 * 8] = std::mem::transmute(regs); + + for i in 0..8 { + for j in 0..i { + let orig = vals[i * 8 + j]; + vals[i * 8 + j] = vals[j * 8 + i]; + vals[j * 8 + i] = orig; + } + } + + for i in 0..8 { + for j in 0..8 { + assert_eq!(vals[j * 8 + i], get_val(i, j)); + assert_eq!(vals_from_reg[j * 8 + i], get_val(i, j)); + } + } + + assert_eq!(vals, vals_from_reg); + } + } +} diff --git a/third_party/zune-jpeg/src/upsampler.rs b/third_party/zune-jpeg/src/upsampler.rs new file mode 100644 index 0000000..5ba10d5 --- /dev/null +++ b/third_party/zune-jpeg/src/upsampler.rs @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +//! Up-sampling routines +//! +//! The main upsampling method is a bi-linear interpolation or a "triangle +//! filter " or libjpeg turbo `fancy_upsampling` which is a good compromise +//! between speed and visual quality +//! +//! # The filter +//! Each output pixel is made from `(3*A+B)/4` where A is the original +//! pixel closer to the output and B is the one further. +//! +//! ```text +//!+---+---+ +//! | A | B | +//! +---+---+ +//! +-+-+-+-+ +//! | |P| | | +//! +-+-+-+-+ +//! ``` +//! +//! # Horizontal Bi-linear filter +//! ```text +//! |---+-----------+---+ +//! | | | | +//! | A | |p1 | p2| | B | +//! | | | | +//! |---+-----------+---+ +//! +//! ``` +//! For a horizontal bi-linear it's trivial to implement, +//! +//! `A` becomes the input closest to the output. +//! +//! `B` varies depending on output. +//! - For odd positions, input is the `next` pixel after A +//! - For even positions, input is the `previous` value before A. +//! +//! We iterate in a classic 1-D sliding window with a window of 3. +//! For our sliding window approach, `A` is the 1st and `B` is either the 0th term or 2nd term +//! depending on position we are writing.(see scalar code). +//! +//! For vector code see module sse for explanation. +//! +//! # Vertical bi-linear. +//! Vertical up-sampling is a bit trickier. +//! +//! ```text +//! +----+----+ +//! | A1 | A2 | +//! +----+----+ +//! +----+----+ +//! | p1 | p2 | +//! +----+-+--+ +//! +----+-+--+ +//! | p3 | p4 | +//! +----+-+--+ +//! +----+----+ +//! | B1 | B2 | +//! +----+----+ +//! ``` +//! +//! For `p1` +//! - `A1` is given a weight of `3` and `B1` is given a weight of 1. +//! +//! For `p3` +//! - `B1` is given a weight of `3` and `A1` is given a weight of 1 +//! +//! # Horizontal vertical downsampling/chroma quartering. +//! +//! Carry out a vertical filter in the first pass, then a horizontal filter in the second pass. +use crate::components::UpSampler; + +mod scalar; + +// choose best possible implementation for this platform +pub fn choose_horizontal_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_horizontal; +} + +pub fn choose_hv_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_hv; +} + +pub fn choose_v_samp_function(_use_unsafe: bool) -> UpSampler { + return scalar::upsample_vertical; +} + +/// Upsample nothing + +pub fn upsample_no_op( + _input: &[i16], _in_ref: &[i16], _in_near: &[i16], _scratch_space: &mut [i16], + _output: &mut [i16] +) { +} diff --git a/third_party/zune-jpeg/src/upsampler/scalar.rs b/third_party/zune-jpeg/src/upsampler/scalar.rs new file mode 100644 index 0000000..a0ca8be --- /dev/null +++ b/third_party/zune-jpeg/src/upsampler/scalar.rs @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +pub fn upsample_horizontal( + input: &[i16], _ref: &[i16], _in_near: &[i16], _scratch: &mut [i16], output: &mut [i16] +) { + assert_eq!( + input.len() * 2, + output.len(), + "Input length is not half the size of the output length" + ); + assert!( + output.len() > 4 && input.len() > 2, + "Too Short of a vector, cannot upsample" + ); + + output[0] = input[0]; + output[1] = (input[0] * 3 + input[1] + 2) >> 2; + + // This code is written for speed and not readability + // + // The readable code is + // + // for i in 1..input.len() - 1{ + // let sample = 3 * input[i] + 2; + // out[i * 2] = (sample + input[i - 1]) >> 2; + // out[i * 2 + 1] = (sample + input[i + 1]) >> 2; + // } + // + // The output of a pixel is determined by it's surrounding neighbours but we attach more weight to it's nearest + // neighbour (input[i]) than to the next nearest neighbour. + + for (output_window, input_window) in output[2..].chunks_exact_mut(2).zip(input.windows(3)) { + let sample = 3 * input_window[1] + 2; + + output_window[0] = (sample + input_window[0]) >> 2; + output_window[1] = (sample + input_window[2]) >> 2; + } + // Get lengths + let out_len = output.len() - 2; + let input_len = input.len() - 2; + + // slice the output vector + let f_out = &mut output[out_len..]; + let i_last = &input[input_len..]; + + // write out manually.. + f_out[0] = (3 * i_last[0] + i_last[1] + 2) >> 2; + f_out[1] = i_last[1]; +} +pub fn upsample_vertical( + input: &[i16], in_near: &[i16], in_far: &[i16], _scratch_space: &mut [i16], output: &mut [i16] +) { + assert_eq!(input.len() * 2, output.len()); + assert_eq!(in_near.len(), input.len()); + assert_eq!(in_far.len(), input.len()); + + let middle = output.len() / 2; + + let (out_top, out_bottom) = output.split_at_mut(middle); + + // for the first row, closest row is in_near + for ((near, far), x) in input.iter().zip(in_near.iter()).zip(out_top) { + *x = (((3 * near) + 2) + far) >> 2; + } + // for the second row, the closest row to input is in_far + for ((near, far), x) in input.iter().zip(in_far.iter()).zip(out_bottom) { + *x = (((3 * near) + 2) + far) >> 2; + } +} + +pub fn upsample_hv( + input: &[i16], in_near: &[i16], in_far: &[i16], scratch_space: &mut [i16], output: &mut [i16] +) { + assert_eq!(input.len() * 4, output.len()); + + let mut t = [0]; + upsample_vertical(input, in_near, in_far, &mut t, scratch_space); + // horizontal upsampling must be done separate for every line + // Otherwise it introduces artifacts that may cause the edge colors + // to appear on the other line. + + // Since this is called for two scanlines/widths currently + // splitting the inputs and outputs into half ensures we only handle + // one scanline per iteration + let scratch_half = scratch_space.len() / 2; + + let output_half = output.len() / 2; + + upsample_horizontal( + &scratch_space[..scratch_half], + &[], + &[], + &mut t, + &mut output[..output_half] + ); + + upsample_horizontal( + &scratch_space[scratch_half..], + &[], + &[], + &mut t, + &mut output[output_half..] + ); +} diff --git a/third_party/zune-jpeg/src/worker.rs b/third_party/zune-jpeg/src/worker.rs new file mode 100644 index 0000000..f16b312 --- /dev/null +++ b/third_party/zune-jpeg/src/worker.rs @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use alloc::format; +use core::convert::TryInto; + +use zune_core::colorspace::ColorSpace; + +use crate::color_convert::ycbcr_to_grayscale; +use crate::components::{Components, SampleRatios}; +use crate::decoder::{ColorConvert16Ptr, MAX_COMPONENTS}; +use crate::errors::DecodeErrors; + +/// fast 0..255 * 0..255 => 0..255 rounded multiplication +/// +/// Borrowed from stb +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +#[inline] +fn blinn_8x8(in_val: u8, y: u8) -> u8 { + let t = i32::from(in_val) * i32::from(y) + 128; + return ((t + (t >> 8)) >> 8) as u8; +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +pub(crate) fn color_convert( + unprocessed: &[&[i16]; MAX_COMPONENTS], color_convert_16: ColorConvert16Ptr, + input_colorspace: ColorSpace, output_colorspace: ColorSpace, output: &mut [u8], width: usize, + padded_width: usize +) -> Result<(), DecodeErrors> // so many parameters.. +{ + // maximum sampling factors are in Y-channel, no need to pass them. + + if input_colorspace.num_components() == 3 && input_colorspace == output_colorspace { + // sort things like RGB to RGB conversion + copy_removing_padding(unprocessed, width, padded_width, output); + return Ok(()); + } + if input_colorspace.num_components() == 4 && input_colorspace == output_colorspace { + copy_removing_padding_4x(unprocessed, width, padded_width, output); + return Ok(()); + } + // color convert + match (input_colorspace, output_colorspace) { + (ColorSpace::YCbCr | ColorSpace::Luma, ColorSpace::Luma) => { + ycbcr_to_grayscale(unprocessed[0], width, padded_width, output); + } + ( + ColorSpace::YCbCr, + ColorSpace::RGB | ColorSpace::RGBA | ColorSpace::BGR | ColorSpace::BGRA + ) => { + color_convert_ycbcr( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::YCCK, ColorSpace::RGB) => { + color_convert_ycck_to_rgb::<3>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + + (ColorSpace::YCCK, ColorSpace::RGBA) => { + color_convert_ycck_to_rgb::<4>( + unprocessed, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + } + (ColorSpace::CMYK, ColorSpace::RGB) => { + color_convert_cymk_to_rgb::<3>(unprocessed, width, padded_width, output); + } + (ColorSpace::CMYK, ColorSpace::RGBA) => { + color_convert_cymk_to_rgb::<4>(unprocessed, width, padded_width, output); + } + // For the other components we do nothing(currently) + _ => { + let msg = format!( + "Unimplemented colorspace mapping from {input_colorspace:?} to {output_colorspace:?}"); + + return Err(DecodeErrors::Format(msg)); + } + } + Ok(()) +} + +/// Copy a block to output removing padding bytes from input +/// if necessary +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn copy_removing_padding( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for (((pix_w, c_w), m_w), y_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + { + for (((pix, c), y), m) in pix_w.chunks_exact_mut(3).zip(c_w).zip(m_w).zip(y_w) { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + } + } +} +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn copy_removing_padding_4x( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * 4) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), y), m), k) in pix_w + .chunks_exact_mut(4) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + pix[0] = *c as u8; + pix[1] = *y as u8; + pix[2] = *m as u8; + pix[3] = *k as u8; + } + } +} +/// Convert YCCK image to rgb +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +fn color_convert_ycck_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + color_convert_ycbcr( + mcu_block, + width, + padded_width, + output_colorspace, + color_convert_16, + output + ); + for (pix_w, m_w) in output + .chunks_exact_mut(width * 3) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for (pix, m) in pix_w.chunks_exact_mut(NUM_COMPONENTS).zip(m_w) { + let m = (*m) as u8; + pix[0] = blinn_8x8(255 - pix[0], m); + pix[1] = blinn_8x8(255 - pix[1], m); + pix[2] = blinn_8x8(255 - pix[2], m); + } + } +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +fn color_convert_cymk_to_rgb( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, output: &mut [u8] +) { + for ((((pix_w, c_w), m_w), y_w), k_w) in output + .chunks_exact_mut(width * NUM_COMPONENTS) + .zip(mcu_block[0].chunks_exact(padded_width)) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(mcu_block[3].chunks_exact(padded_width)) + { + for ((((pix, c), m), y), k) in pix_w + .chunks_exact_mut(3) + .zip(c_w) + .zip(m_w) + .zip(y_w) + .zip(k_w) + { + let c = *c as u8; + let m = *m as u8; + let y = *y as u8; + let k = *k as u8; + + pix[0] = blinn_8x8(c, k); + pix[1] = blinn_8x8(m, k); + pix[2] = blinn_8x8(y, k); + } + } +} + +/// Do color-conversion for interleaved MCU +#[allow( + clippy::similar_names, + clippy::too_many_arguments, + clippy::needless_pass_by_value, + clippy::unwrap_used +)] +fn color_convert_ycbcr( + mcu_block: &[&[i16]; MAX_COMPONENTS], width: usize, padded_width: usize, + output_colorspace: ColorSpace, color_convert_16: ColorConvert16Ptr, output: &mut [u8] +) { + let num_components = output_colorspace.num_components(); + + let stride = width * num_components; + // Allocate temporary buffer for small widths less than 16. + let mut temp = [0; 64]; + // We need to chunk per width to ensure we can discard extra values at the end of the width. + // Since the encoder may pad bits to ensure the width is a multiple of 8. + for (((y_width, cb_width), cr_width), out) in mcu_block[0] + .chunks_exact(padded_width) + .zip(mcu_block[1].chunks_exact(padded_width)) + .zip(mcu_block[2].chunks_exact(padded_width)) + .zip(output.chunks_exact_mut(stride)) + { + if width < 16 { + // allocate temporary buffers for the values received from idct + let mut y_out = [0; 16]; + let mut cb_out = [0; 16]; + let mut cr_out = [0; 16]; + // copy those small widths to that buffer + y_out[0..y_width.len()].copy_from_slice(y_width); + cb_out[0..cb_width.len()].copy_from_slice(cb_width); + cr_out[0..cr_width.len()].copy_from_slice(cr_width); + // we handle widths less than 16 a bit differently, allocating a temporary + // buffer and writing to that and then flushing to the out buffer + // because of the optimizations applied below, + (color_convert_16)(&y_out, &cb_out, &cr_out, &mut temp, &mut 0); + // copy to stride + out[0..width * num_components].copy_from_slice(&temp[0..width * num_components]); + // next + continue; + } + + // Chunk in outputs of 16 to pass to color_convert as an array of 16 i16's. + for (((y, cb), cr), out_c) in y_width + .chunks_exact(16) + .zip(cb_width.chunks_exact(16)) + .zip(cr_width.chunks_exact(16)) + .zip(out.chunks_exact_mut(16 * num_components)) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + out_c, + &mut 0 + ); + } + //we have more pixels in the end that can't be handled by the main loop. + //move pointer back a little bit to get last 16 bytes, + //color convert, and overwrite + //This means some values will be color converted twice. + for ((y, cb), cr) in y_width[width - 16..] + .chunks_exact(16) + .zip(cb_width[width - 16..].chunks_exact(16)) + .zip(cr_width[width - 16..].chunks_exact(16)) + .take(1) + { + (color_convert_16)( + y.try_into().unwrap(), + cb.try_into().unwrap(), + cr.try_into().unwrap(), + &mut temp, + &mut 0 + ); + } + + let rem = out[(width - 16) * num_components..] + .chunks_exact_mut(16 * num_components) + .next() + .unwrap(); + + rem.copy_from_slice(&temp[0..rem.len()]); + } +} +pub(crate) fn upsample( + component: &mut Components, mcu_height: usize, i: usize, upsampler_scratch_space: &mut [i16] +) { + match component.sample_ratio { + SampleRatios::V | SampleRatios::HV => { + /* + When upsampling vertically sampled images, we have a certain problem + which is that we do not have all MCU's decoded, this usually sucks at boundaries + e.g we can't upsample the last mcu row, since the row_down currently doesn't exist + + To solve this we need to do two things + + 1. Carry over coefficients when we lack enough data to upsample + 2. Upsample when we have enough data + + To achieve (1), we store a previous row, and the current row in components themselves + which will later be used to make (2) + + To achieve (2), we take the stored previous row(second last MCU row), + current row(last mcu row) and row down(first row of newly decoded MCU) + + and upsample that and store it in first_row_upsample_dest, this contains + up-sampled coefficients for the last for the previous decoded mcu row. + + The caller is then expected to process first_row_upsample_dest before processing data + in component.upsample_dest which stores the up-sampled components excluding the last row + */ + + let mut dest_start = 0; + let stride_bytes_written = component.width_stride * component.sample_ratio.sample(); + + if i > 0 { + // Handle the last MCU of the previous row + // This wasn't up-sampled as we didn't have the row_down + // so we do it now + + let stride = component.width_stride; + + let dest = &mut component.first_row_upsample_dest[0..stride_bytes_written]; + + // get current row + let row = &component.row[..]; + let row_up = &component.row_up[..]; + let row_down = &component.raw_coeff[0..stride]; + (component.up_sampler)(row, row_up, row_down, upsampler_scratch_space, dest); + } + + // we have the Y component width stride. + // this may be higher than the actual width,(2x because vertical sampling) + // + // This will not upsample the last row + + // if false, do not upsample. + // set to false on the last row of an mcu + let mut upsample = true; + + let stride = component.width_stride * component.vertical_sample; + let stop_offset = component.raw_coeff.len() / component.width_stride; + for (pos, curr_row) in component + .raw_coeff + .chunks_exact(component.width_stride) + .enumerate() + { + let mut dest: &mut [i16] = &mut []; + let mut row_up: &[i16] = &[]; + // row below current sample + let mut row_down: &[i16] = &[]; + + // Order of ifs matters + + if i == 0 && pos == 0 { + // first IMAGE row, row_up is the same as current row + // row_down is the row below. + row_up = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i > 0 && pos == 0 { + // first row of a new mcu, previous row was copied so use that + row_up = &component.row[..]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if i == mcu_height.saturating_sub(1) && pos == stop_offset - 1 { + // last IMAGE row, adjust pointer to use previous row and current row + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[pos * stride..(pos + 1) * stride]; + } else if pos > 0 && pos < stop_offset - 1 { + // other rows, get row up and row down relative to our current row + // ignore last row of each mcu + row_up = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + row_down = &component.raw_coeff[(pos + 1) * stride..(pos + 2) * stride]; + } else if pos == stop_offset - 1 { + // last MCU in a row + // + // we need a row at the next MCU but we haven't decoded that MCU yet + // so we should save this and when we have the next MCU, + // do the upsampling + + // store the current row and previous row in a buffer + let prev_row = &component.raw_coeff[(pos - 1) * stride..pos * stride]; + + component.row_up.copy_from_slice(prev_row); + component.row.copy_from_slice(curr_row); + upsample = false; + } else { + unreachable!("Uh oh!"); + } + if upsample { + dest = + &mut component.upsample_dest[dest_start..dest_start + stride_bytes_written]; + dest_start += stride_bytes_written; + } + + if upsample { + // upsample + (component.up_sampler)( + curr_row, + row_up, + row_down, + upsampler_scratch_space, + dest + ); + } + } + } + SampleRatios::H => { + assert_eq!(component.raw_coeff.len() * 2, component.upsample_dest.len()); + + let raw_coeff = &component.raw_coeff; + let dest_coeff = &mut component.upsample_dest; + + // upsample each row + for (single_row, output_stride) in raw_coeff + .chunks_exact(component.width_stride) + .zip(dest_coeff.chunks_exact_mut(component.width_stride * 2)) + { + // upsample using the fn pointer, should only be H, so no need for + // row up and row down + (component.up_sampler)(single_row, &[], &[], &mut [], output_stride); + } + } + SampleRatios::None => {} + }; +} diff --git a/third_party/zune-jpeg/tests/invalid_images.rs b/third_party/zune-jpeg/tests/invalid_images.rs new file mode 100644 index 0000000..c6f22d6 --- /dev/null +++ b/third_party/zune-jpeg/tests/invalid_images.rs @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023. + * + * This software is free software; + * + * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license + */ + +use zune_core::bytestream::ZCursor; +use zune_jpeg::JpegDecoder; + +#[test] +fn eof() { + let mut decoder = JpegDecoder::new(ZCursor::new([0xff, 0xd8, 0xa4])); + + decoder.decode().unwrap_err(); +} + +#[test] +fn bad_ff_marker_size() { + let mut decoder = JpegDecoder::new(ZCursor::new([0xff, 0xd8, 0xff, 0x00, 0x00, 0x00])); + + let _ = decoder.decode().unwrap_err(); +} + +#[test] +fn bad_number_of_scans() { + let mut decoder = JpegDecoder::new(ZCursor::new([255, 216, 255, 218, 232, 197, 255])); + + let err = decoder.decode().unwrap_err(); + + assert!( + matches!(err, zune_jpeg::errors::DecodeErrors::SosError(x) if x == "Bad SOS length 59589,corrupt jpeg") + ); +} + +#[test] +fn huffman_length_subtraction_overflow() { + let mut decoder = JpegDecoder::new(ZCursor::new([255, 216, 255, 196, 0, 0])); + + let err = decoder.decode().unwrap_err(); + + assert!( + matches!(err, zune_jpeg::errors::DecodeErrors::FormatStatic(x) if x == "Invalid Huffman length in image") + ); +} + +#[test] +fn index_oob() { + let mut decoder = JpegDecoder::new(ZCursor::new([255, 216, 255, 218, 0, 8, 1, 0, 8, 1])); + + let _ = decoder.decode().unwrap_err(); +} + +#[test] +fn mul_with_overflow() { + let mut decoder = JpegDecoder::new(ZCursor::new([ + 255, 216, 255, 192, 255, 1, 8, 9, 119, 48, 255, 192 + ])); + + let err = decoder.decode().unwrap_err(); + + assert!( + matches!(err, zune_jpeg::errors::DecodeErrors::SofError(x) if x == "Length of start of frame differs from expected 584,value is 65281") + ); +}

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�w8Xx=JMBo) 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