├── .github └── workflows │ └── rust.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── appveyor.yml ├── benches ├── decoding_benchmark.rs ├── large_image.jpg ├── large_image.rs ├── tower.jpg ├── tower_grayscale.jpg └── tower_progressive.jpg ├── examples └── decode.rs ├── fuzz-afl ├── .gitignore ├── Cargo.toml ├── README.md ├── in │ ├── 4x4.jpg │ ├── grass.jpg │ ├── id_000006,src_000000,op_flip1,pos_3,+cov.jpg │ ├── id_000023,src_000000,op_flip1,pos_21,+cov.jpg │ ├── id_000034,src_000000,op_flip1,pos_159,+cov.jpg │ ├── id_000046,src_000000,op_flip1,pos_164,+cov.jpg │ ├── id_000056,src_000000,op_flip1,pos_166,+cov.jpg │ ├── id_000071,src_000000,op_flip1,pos_172.jpg │ ├── id_000081,src_000000,op_flip1,pos_181,+cov.jpg │ ├── id_000170,src_000000,op_flip1,pos_307,+cov.jpg │ ├── id_000182,src_000000,op_flip1,pos_503,+cov.jpg │ ├── id_000186,src_000000,op_flip2,pos_21,+cov.jpg │ ├── id_000195,src_000000,op_flip2,pos_167,+cov.jpg │ ├── id_000202,src_000000,op_flip2,pos_178,+cov.jpg │ ├── id_000223,src_000000,op_flip2,pos_503,+cov.jpg │ ├── id_000224,src_000000,op_flip2,pos_299.jpg │ ├── id_000227,src_000000,op_flip2,pos_503,+cov.jpg │ ├── id_000305,src_000000,op_arith8,pos_295,val_+20,+cov.jpg │ ├── id_000324,src_000000,op_arith16,pos_227,val_be_-16.jpg │ ├── id_000338,src_000000,op_int8,pos_23,val_+0,+cov.jpg │ ├── id_000386,src_000000,op_havoc,rep_128,+cov.jpg │ ├── id_000393,src_000000,op_int32,pos_500,val_-32768,+cov.jpg │ ├── id_000397,src_000000,op_havoc,rep_64.jpg │ ├── id_000400,src_000000,op_havoc,rep_64,+cov.jpg │ ├── id_000416,src_000000,op_havoc,rep_16.jpg │ ├── id_000448,src_000000,op_havoc,rep_32,+cov.jpg │ ├── id_000449,src_000000,op_havoc,rep_16,+cov.jpg │ ├── id_000508,src_000000,op_havoc,rep_16,+cov.jpg │ ├── id_000514,src_000000,op_havoc,rep_16,+cov.jpg │ ├── id_000514,src_000000,op_havoc,rep_32,+cov.jpg │ ├── id_000528,src_000000,op_havoc,rep_8.jpg │ ├── id_000568,src_000000,op_havoc,rep_8,+cov.jpg │ ├── id_000578,src_000000,op_havoc,rep_8,+cov.jpg │ ├── id_000594,sync_jpeg_turbo,src_000580.jpg │ ├── id_000597,sync_jpeg_turbo,src_000558.jpg │ ├── id_000647,src_000035,op_flip1,pos_305,+cov.jpg │ ├── id_000667,src_000035,op_int16,pos_306,val_be_+32,+cov.jpg │ ├── id_000681,src_000036,op_int8,pos_306,val_+1,+cov.jpg │ ├── id_000687,sync_jpeg9,src_001936,+cov.jpg │ ├── id_000827,sync_jpeg9,src_001156.jpg │ ├── id_000831,sync_jpeg9,src_000903.jpg │ ├── id_000838,sync_jpeg9,src_000485,+cov.jpg │ ├── id_000885,sync_jpeg9,src_000654,+cov.jpg │ ├── id_000903,src_000177,op_havoc,rep_2.jpg │ ├── id_000961,sync_jpeg9,src_002802.jpg │ ├── id_000989,sync_jpeg9,src_001094.jpg │ ├── id_001085,sync_jpeg9,src_000887,+cov.jpg │ ├── id_001086,sync_jpeg9,src_000744.jpg │ ├── id_001118,sync_jpeg9,src_000623.jpg │ ├── id_001136,sync_jpeg9,src_000760,+cov.jpg │ ├── id_001156,sync_jpeg9,src_000847,+cov.jpg │ ├── id_001211,sync_jpeg9,src_001184.jpg │ ├── id_001259,sync_jpeg9,src_001469,+cov.jpg │ ├── id_001265,sync_jpeg9,src_000512,+cov.jpg │ ├── id_001346,sync_jpeg9,src_000740.jpg │ ├── id_001366,sync_jpeg9,src_000537,+cov.jpg │ ├── id_001386,src_000607,op_int32,pos_183,val_be_+1.jpg │ ├── id_001411,src_000636,op_flip4,pos_165,+cov.jpg │ ├── id_001427,src_000319,op_havoc,rep_1.jpg │ ├── id_001458,src_000531,op_flip4,pos_287.jpg │ ├── id_001467,src_000666,op_flip4,pos_307,+cov.jpg │ ├── id_001505,src_000633,op_flip1,pos_2,+cov.jpg │ ├── id_001655,src_001333,op_flip2,pos_455.jpg │ ├── id_001696,src_001527,op_arith8,pos_296,val_-17.jpg │ ├── id_001744,src_001635,op_arith8,pos_164,val_-28.jpg │ ├── id_001792,src_000728,op_int32,pos_227,val_be_+1000.jpg │ ├── id_001952,src_001930,op_havoc,rep_4.jpg │ ├── id_002005,src_001056,op_flip2,pos_175.jpg │ ├── id_002075,src_001092,op_arith8,pos_209,val_+20,+cov.jpg │ ├── id_002199,sync_jpeg_turbo,src_001677.jpg │ ├── id_002306,src_001438,op_flip4,pos_290,+cov.jpg │ ├── id_002423,src_001504,op_arith32,pos_300,val_-13.jpg │ ├── id_002987,sync_jpeg_turbo,src_001510,+cov.jpg │ ├── id_003091,src_002994,op_flip1,pos_159,+cov.jpg │ ├── id_003098,src_003010,op_flip4,pos_27.jpg │ ├── id_003112,src_003036,op_arith8,pos_175,val_+13.jpg │ ├── id_003131,src_003114,op_havoc,rep_128,+cov.jpg │ ├── id_003141,sync_jpeg_turbo,src_001694.jpg │ ├── id_003632,src_003613,op_havoc,rep_8.jpg │ ├── id_003685,sync_jpeg_turbo,src_002052,+cov.jpg │ ├── id_003813,sync_jpeg_turbo,src_002223.jpg │ ├── id_004086,sync_jpeg_turbo,src_002441.jpg │ ├── id_004141,src_004138,op_int8,pos_44,val_+1,+cov.jpg │ ├── id_004143,src_003886+004101,op_splice,rep_2.jpg │ ├── id_004173,sync_jpeg_turbo,src_002577.jpg │ ├── id_004289,sync_jpeg_turbo,src_002582.jpg │ ├── id_004294,src_004289,op_flip2,pos_104.jpg │ ├── id_004356,src_004355,op_flip1,pos_49.jpg │ ├── id_004623,src_004596,op_havoc,rep_4.jpg │ ├── id_004630,src_004598,op_arith8,pos_93,val_+9.jpg │ ├── id_004675,src_004650,op_flip1,pos_103.jpg │ ├── id_004829,sync_jpeg_turbo_extras,src_002309.jpg │ ├── id_004851,sync_jpeg_turbo,src_003589.jpg │ ├── id_004887,src_004848,op_flip1,pos_284.jpg │ ├── id_005371,src_004601,op_havoc,rep_2.jpg │ ├── id_005661,src_005658,op_havoc,rep_8,+cov.jpg │ ├── id_005679,src_005671,op_havoc,rep_1,+cov.jpg │ ├── id_005745,src_005744,op_flip1,pos_97.jpg │ ├── id_005758,sync_jpeg_turbo,src_004354.jpg │ ├── id_005761,src_005759,op_flip1,pos_52.jpg │ ├── relax-jpeg.jpg │ ├── relax-jpeg2000.jp2 │ ├── window-q0.jpg │ └── window-q20.jpg └── src │ ├── fuzz_decode.rs │ ├── fuzz_info.rs │ ├── reproduce_decode.rs │ ├── reproduce_info.rs │ └── utils.rs ├── fuzz ├── .gitignore ├── Cargo.toml ├── Readme.md └── fuzz_targets │ ├── fail_tmin.rs │ └── regression.rs ├── rust-toolchain ├── src ├── arch │ ├── mod.rs │ ├── neon.rs │ ├── ssse3.rs │ └── wasm.rs ├── decoder.rs ├── decoder │ └── lossless.rs ├── error.rs ├── huffman.rs ├── idct.rs ├── lib.rs ├── marker.rs ├── parser.rs ├── upsampler.rs └── worker │ ├── immediate.rs │ ├── mod.rs │ ├── multithreaded.rs │ └── rayon.rs └── tests ├── common └── mod.rs ├── crashtest ├── images │ ├── README.md │ ├── dc-predictor-overflow.jpg │ ├── derive-huffman-codes-overflow.jpg │ ├── empty.jpg │ ├── extraneous-bytes-after-sos.jpg │ ├── imagetestsuite │ │ ├── 138d3b9e0d9fbf641b8135981e597c3a.jpg │ │ ├── 194531363df5b73f59c4c0517422f917.jpg │ │ ├── 1cbb1bb37d62c44f67374cd451643dc4.jpg │ │ ├── 2183d39878e734cf79b62428b02fafb5.jpg │ │ ├── 21a84b8472f6d18f5bb5c0026e97cfaa.jpg │ │ ├── 21ad703b38e2c350215bb92a849486f3.jpg │ │ ├── 255015e07b6f9137b53b0f97d67a8aef.jpg │ │ ├── 28968137f4fc75fbf56f16d7a7a8551a.jpg │ │ ├── 28c74d9284d9836017fd519f6932efd8.jpg │ │ ├── 2c9e7a1805f8b47630bbb83d21bf8222.jpg │ │ ├── 316be81dfdeeb942e904feb3a77f4f83.jpg │ │ ├── 32d08f4a5eb10332506ebedbb9bc7257.jpg │ │ ├── 3976a754ef0aca80e84e2c403d714579.jpg │ │ ├── 39f43f280b31152f1d27df3f9d189317.jpg │ │ ├── 3ba6af611cc5467cfdbd5566561b8478.jpg │ │ ├── 3cc4a7fc6481ea3681138da4643f3d16.jpg │ │ ├── 3ea649db8e81a46ca4f92fb3238f78ff.jpg │ │ ├── 3ef05501315073d9d4e1c6b654d99ac0.jpg │ │ ├── 4085c929e00c446d3fee18b5b20a27f9.jpg │ │ ├── 40bb78b1ac031125a6d8466b374962a8.jpg │ │ ├── 46e5ac4a62d7a445a7c1fb704fafe05c.jpg │ │ ├── 46f5d9c1b0fe352353688f736e5617b6.jpg │ │ ├── 4838ece0d3900220d33528ee027289bc.jpg │ │ ├── 5315c35bbcc28d8eee419028ac9f38e0.jpg │ │ ├── 5482a54657765056f1a94116a8dbffe7.jpg │ │ ├── 551c2656a4f6f9f5ea7e9945b9081202.jpg │ │ ├── 5633ed9d0eb700d0093bf85d86a95ebf.jpg │ │ ├── 56d4a1bb53241f7c5ed6ab531320a542.jpg │ │ ├── 59d3b529c78ac722127c41ba75b3355b.jpg │ │ ├── 5a43fa2cf9c1e47f0331ef71b928ee55.jpg │ │ ├── 5baad44ca4702949724234e35c5bb341.jpg │ │ ├── 5bc61724b33e34a6188a817f9f2f8138.jpg │ │ ├── 5c67195f6993c9f8d0d32d4ffe0d8e62.jpg │ │ ├── 5dc71b1d868ef137394d3cc23abea65a.jpg │ │ ├── 627c0779eb46b98f751187c5c9f43aa3.jpg │ │ ├── 6903d4538fd33c8fd0ded32cb30d618e.jpg │ │ ├── 6de166ee2a3a60df9017650e2a808408.jpg │ │ ├── 72d091e08c93c9e590360130fa35221b.jpg │ │ ├── 754664a12e36abff7950e796c906ae39.jpg │ │ ├── 75e4bd7544a85af6438497980b62fba5.jpg │ │ ├── 786b67badc535fc95a4a76c29a0e0146.jpg │ │ ├── 7997b6b229f25315d33f5c7085e37500.jpg │ │ ├── 79f5fc6bca756e1f067c6fc83e18b32e.jpg │ │ ├── 7acc832f70b2ca62e58a953f3b90fd82.jpg │ │ ├── 7dbf474f80e466e9e25ee46b84166420.jpg │ │ ├── 7e7cdf7f4ee50b308531313bbf43e0c3.jpg │ │ ├── 8417a305e3b43d5b1bda4ff06a660c54.jpg │ │ ├── 8546907dbe574744d7fea6ca9de1de6b.jpg │ │ ├── 865db3dd2d380626f16b6f9dc6d62dba.jpg │ │ ├── 897b8b6d8feb466aa6cad5f512c3fce2.jpg │ │ ├── 8a9cc8eeed66aeb423a91c44111d9450.jpg │ │ ├── 8e330afbd99ba01b66570ed62fcdc6ab.jpg │ │ ├── 8e5e74dbf9b68a322fbb9512db837329.jpg │ │ ├── 90e46387f562ca8fa106b51dfcda1dc6.jpg │ │ ├── 96b3e939852157613fa2e48d58fe35fe.jpg │ │ ├── 9efd60f04cd971daa83d3131e6d6f389.jpg │ │ ├── a17806f32b45d63eea5230e7893e1f15.jpg │ │ ├── a54f8c866cbef6e6cda858c85d72dfc8.jpg │ │ ├── a7326ba8f3f4559991126474dd30083d.jpg │ │ ├── acb1fac4e618f636d415f62496e8b70e.jpg │ │ ├── acce3629083f0e348e94fb58f952d3de.jpg │ │ ├── adcb34b94f4c839bdd29037419a0ee53.jpg │ │ ├── b0b8914cc5f7a6eff409f16d8cc236c5.jpg │ │ ├── b4103df93880fc5677c2a081e4bfc712.jpg │ │ ├── b5369bcbddca7135a5708c5237ad64e4.jpg │ │ ├── b55977028a3a574336966b6536640fc9.jpg │ │ ├── ba60305ac83fe3d8ef01da1d9a0ecc79.jpg │ │ ├── bd8cf05698aee36b82b4caf58edea442.jpg │ │ ├── c1ca5583e4bfadc73e7fe9418b6e6bf4.jpg │ │ ├── c3018ebe53d0046eecb58858ca869a99.jpg │ │ ├── c4ced510f44a9bfe85c696c05a7f791d.jpg │ │ ├── c52ffdd6a0346c4d09271f8ccbdfd5a3.jpg │ │ ├── c8bc97335529d069a753c67475b8c82c.jpg │ │ ├── c8c1a5675f82021d92b928a10c597bad.jpg │ │ ├── cc23dd79637b606cf5ba234a037e17ba.jpg │ │ ├── cc4ee796d16c9fe68978166c7cd1ae1b.jpg │ │ ├── ce380515a534e8226209daae00e7b4e8.jpg │ │ ├── d085a42245996e5750a30ccb48791bcf.jpg │ │ ├── d15b71b8cebe35a57cc6e996cc09218b.jpg │ │ ├── d22db5be7594c17a18a047ca9264ea0a.jpg │ │ ├── d3b044a94486cae0224c002800ddd642.jpg │ │ ├── de4ae285a275bcfe2ac87c0126742552.jpg │ │ ├── de5884cec093257d239f3b8be3e2f2e5.jpg │ │ ├── e18bb52107598f65b81b02be2c6c5124.jpg │ │ ├── e6d9eca2c7405e13cfb850b7d0ef7476.jpg │ │ ├── eddea4ef9629be031f750a8ff0b7497c.jpg │ │ ├── eecb78b937a7c5f04aae2f5b0f5b5acc.jpg │ │ ├── ef1f8a057bb6056674fad92f6b8c0acd.jpg │ │ ├── ef724193653930f52acffa90e6426fd2.jpg │ │ ├── f006e96f3b27fdfaa075322d759ea2e8.jpg │ │ ├── f012a4321f00f12af6b1eee7580ffb9c.jpg │ │ ├── f1fad47f213bb64c99f714652f30e49e.jpg │ │ ├── f6419b06a39ff09604343848658b1a41.jpg │ │ ├── f6b4389c3cf0f5997b2e5a4b905aea8d.jpg │ │ ├── f6d3f522dcb693d9e731d5a0fb4e1393.jpg │ │ ├── f8e19feecd246156b5d7e79efc455e99.jpg │ │ ├── fd44dc63fa7bdd12ee34fc602231ef02.jpg │ │ └── fddcfc778ada60229380c2493fc4c243.jpg │ ├── invalid-dimensions.jpg │ ├── invalid-prediction-shift.jpg │ ├── max_size.jpg │ ├── missing-frame-image-1410.jpg │ ├── missing-sof.jpg │ ├── missing-sos.jpg │ ├── multiple-0xff-before-eoi.jpg │ ├── null_height.jpg │ └── subtract-with-overflow.jpg └── mod.rs ├── icc ├── icc_chunk_count_mismatch.jpeg ├── icc_chunk_double_seq_no.jpeg ├── icc_chunk_order.jpeg ├── icc_chunk_seq_no_0.jpeg └── icc_missing_chunk.jpeg ├── lib.rs ├── rayon-0.rs ├── rayon-1.rs ├── rayon-2.rs ├── rayon.rs └── reftest ├── .gitignore ├── images ├── 16bit-qtables.jpg ├── 16bit-qtables.png ├── README.md ├── blank_800x280.jpg ├── blank_800x280.png ├── disabled.list ├── extraneous-data.jpg ├── extraneous-data.png ├── grayscale_16x24_sampling2x2.jpg ├── grayscale_16x24_sampling2x2.png ├── grayscale_24x16_sampling2x2.jpg ├── grayscale_24x16_sampling2x2.png ├── grayscale_large.jpg ├── grayscale_large.png ├── grayscale_long.jpg ├── grayscale_long.png ├── grayscale_square.jpg ├── grayscale_square.png ├── lossless │ ├── 1 │ │ ├── LICENSE │ │ ├── README.md │ │ ├── jpeg_lossless_sel1-8bit.jpg │ │ ├── jpeg_lossless_sel1-8bit.png │ │ ├── jpeg_lossless_sel1-rgb.jpg │ │ ├── jpeg_lossless_sel1-rgb.png │ │ ├── jpeg_lossless_sel1.jpg │ │ ├── jpeg_lossless_sel1.png │ │ ├── jpeg_lossless_sel2.jpg │ │ ├── jpeg_lossless_sel2.png │ │ ├── jpeg_lossless_sel3.jpg │ │ ├── jpeg_lossless_sel3.png │ │ ├── jpeg_lossless_sel4.jpg │ │ ├── jpeg_lossless_sel4.png │ │ ├── jpeg_lossless_sel5.jpg │ │ ├── jpeg_lossless_sel5.png │ │ ├── jpeg_lossless_sel6.jpg │ │ ├── jpeg_lossless_sel6.png │ │ ├── jpeg_lossless_sel7.jpg │ │ ├── jpeg_lossless_sel7.png │ │ ├── lossless16bit.jpg │ │ └── lossless16bit.png │ └── 2 │ │ ├── MR4.jpg │ │ ├── MR4.png │ │ ├── README.md │ │ ├── XA1.jpg │ │ └── XA1.png ├── mjpeg.jpg ├── mjpeg.png ├── mozilla │ ├── README.md │ ├── jpg-cmyk-1.jpg │ ├── jpg-cmyk-1.png │ ├── jpg-cmyk-2.jpg │ ├── jpg-cmyk-2.png │ ├── jpg-gray.jpg │ ├── jpg-gray.png │ ├── jpg-progressive.jpg │ ├── jpg-progressive.png │ ├── jpg-size-15x15.jpg │ ├── jpg-size-15x15.png │ ├── jpg-size-16x16.jpg │ ├── jpg-size-16x16.png │ ├── jpg-size-17x17.jpg │ ├── jpg-size-17x17.png │ ├── jpg-size-1x1.jpg │ ├── jpg-size-1x1.png │ ├── jpg-size-2x2.jpg │ ├── jpg-size-2x2.png │ ├── jpg-size-31x31.jpg │ ├── jpg-size-31x31.png │ ├── jpg-size-32x32.jpg │ ├── jpg-size-32x32.png │ ├── jpg-size-33x33.jpg │ ├── jpg-size-33x33.png │ ├── jpg-size-3x3.jpg │ ├── jpg-size-3x3.png │ ├── jpg-size-4x4.jpg │ ├── jpg-size-4x4.png │ ├── jpg-size-5x5.jpg │ ├── jpg-size-5x5.png │ ├── jpg-size-6x6.jpg │ ├── jpg-size-6x6.png │ ├── jpg-size-7x7.jpg │ ├── jpg-size-7x7.png │ ├── jpg-size-8x8.jpg │ ├── jpg-size-8x8.png │ ├── jpg-size-9x9.jpg │ ├── jpg-size-9x9.png │ ├── jpg-srgb-icc.jpg │ └── jpg-srgb-icc.png ├── non-interleaved-mcu.jpg ├── non-interleaved-mcu.png ├── partial_progressive.jpg ├── partial_progressive.png ├── progressive-missing-ac.jpg ├── progressive-missing-ac.png ├── progressive-missing-dc.jpg ├── progressive-missing-dc.png ├── progressive3.jpg ├── progressive3.png ├── restarts.jpg ├── restarts.png ├── rgb.jpg ├── rgb.png ├── rgb_125x84.png ├── rgb_250x167.png ├── rgb_63x42.png ├── ycck.jpg └── ycck.png └── mod.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust CI 2 | 3 | on: 4 | push: 5 | branches: [master, github-actions] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | rust: ["1.61.0", stable, beta, nightly] 16 | features: ["", "rayon"] 17 | command: [test, benchmark] 18 | 19 | steps: 20 | - name: Installing Rust toolchain 21 | uses: actions-rs/toolchain@v1 22 | with: 23 | override: true 24 | toolchain: ${{ matrix.rust }} 25 | - uses: actions/checkout@v2 26 | - name: build 27 | run: > 28 | cargo build --verbose --no-default-features --features "$FEATURES" 29 | - name: test 30 | run: > 31 | cargo test --tests --benches --no-default-features --features "$FEATURES" 32 | if: ${{ matrix.command == 'test' && matrix.rust != '1.61.0' }} 33 | env: 34 | FEATURES: ${{ matrix.features }} 35 | - name: benchmark 36 | run: cargo bench --bench decoding_benchmark --no-default-features --features "$FEATURES" -- --warm-up-time 1 --measurement-time 1 --sample-size 25 37 | if: ${{ matrix.command == 'benchmark' && matrix.rust != '1.61.0' }} 38 | env: 39 | FEATURES: ${{ matrix.features }} 40 | 41 | cross_compile_aarch64: 42 | runs-on: ubuntu-latest 43 | 44 | strategy: 45 | matrix: 46 | rust: [nightly-2024-01-13] 47 | features: ["", "rayon", "nightly_aarch64_neon"] 48 | 49 | steps: 50 | - name: Installing emulator and linker 51 | run: | 52 | sudo apt-get update 53 | sudo apt-get install qemu-system binfmt-support qemu-user-static gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu 54 | 55 | - name: Installing Rust toolchain 56 | uses: actions-rs/toolchain@v1 57 | with: 58 | override: true 59 | toolchain: ${{ matrix.rust }} 60 | target: aarch64-unknown-linux-musl 61 | - uses: actions/checkout@v2 62 | - name: build 63 | run: > 64 | cargo build --verbose --no-default-features --target aarch64-unknown-linux-musl --features "$FEATURES" 65 | env: 66 | CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: aarch64-linux-gnu-gcc 67 | - name: test 68 | run: > 69 | cargo test --tests --benches --no-default-features --target aarch64-unknown-linux-musl --features "$FEATURES" 70 | env: 71 | FEATURES: ${{ matrix.features }} 72 | CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: aarch64-linux-gnu-gcc 73 | cross_compile_wasm: 74 | runs-on: ubuntu-latest 75 | steps: 76 | - name: Install node 77 | run: | 78 | sudo apt-get update 79 | sudo apt-get install nodejs 80 | node -v 81 | - name: Install wasm-bindgen 82 | run: > 83 | curl -L "$WASMBINDGEN_UPSTREAM" 84 | | tar xzf - --strip-components=1 wasm-bindgen-0.2.89-x86_64-unknown-linux-musl/wasm-bindgen-test-runner 85 | && sudo mv wasm-bindgen-test-runner /usr/bin/wasm-bindgen-test-runner 86 | env: 87 | WASMBINDGEN_UPSTREAM: https://github.com/rustwasm/wasm-bindgen/releases/download/0.2.89/wasm-bindgen-0.2.89-x86_64-unknown-linux-musl.tar.gz 88 | - name: Installing Rust toolchain 89 | uses: actions-rs/toolchain@v1 90 | with: 91 | override: true 92 | toolchain: stable 93 | target: wasm32-unknown-unknown 94 | - uses: actions/checkout@v2 95 | - name: Test 96 | run: | 97 | cargo update 98 | # update wasm-bindgen to the version we want and bring -test along for the ride 99 | cargo update -p wasm-bindgen --precise 0.2.89 -p wasm-bindgen-test 100 | cargo test -vv --target wasm32-unknown-unknown 101 | env: 102 | CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: wasm-bindgen-test-runner 103 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## v0.3.1 (2024-01-13) 6 | 7 | - Added a WASM SIMD implementation. 8 | - Allow reading the XMP packet. 9 | - Admit more precision values in JPEG Lossless. 10 | 11 | ## v0.3.0 (2022-10-17) 12 | 13 | - The MSRV policy is now managed by the `rust-version` field in `Cargo.toml`. 14 | - The color transform can now be overridden as well as hinted with 15 | `Decoder::set_color_transform`. 16 | 17 | ## v0.2.6 (2022-05-09) 18 | 19 | - Another fix to allow usage in WASM target. 20 | - Decoding in the WASM target is now actively tested in CI. 21 | 22 | ## v0.2.5 (2022-05-02) 23 | 24 | - Fix single threaded usage in WASM target. 25 | 26 | ## v0.2.4 (2022-04-01) 27 | 28 | - Corrects minimal version requirements of dependency `rayon`. 29 | 30 | ## v0.2.3 (2022-02-14) 31 | 32 | - Added `Decoder::set_max_decoding_buffer_size` which limits the bytes 33 | allocated for the output of the decoding process. 34 | - Added Arm64-Neon intrinsic implementation of idct and color conversion. This 35 | depends on a Rust nightly compiler feature ([`aarch64_target_feature`]) and 36 | it must be explicitly enabled. As soon as the minimum supported Rust version 37 | includes the stabilization of this feature, the code will be enabled by 38 | default and the feature changed to do nothing. 39 | 40 | [`aarch64_target_feature`]: https://github.com/rust-lang/rust/issues/90620 41 | 42 | ## v0.2.2 (2022-02-12) 43 | 44 | - Added and SSE3-specific SIMD intrinsic implementation for idct and color 45 | conversion. It will run if applicable targets are detect at _runtime_. 46 | - The SIMD implementation is not bit-for-bit compatible with non-SIMD output. 47 | You can enable the `platform_independent` feature, to ensure that only 48 | bit-for-bit equivalent code runs and output is the same on all platforms. 49 | - Improved performance some more by avoiding bounds checks with array types. 50 | - Multithreading is now used more frequently, without the rayon target, except 51 | on an explicit list of unsupported platforms. 52 | 53 | ## v0.2.1 (2022-12-09) 54 | 55 | - Fix decoding error due to conflict of lossless with some spectral selections. 56 | 57 | ## v0.2.0 (2021-12-04) 58 | 59 | - Added Lossless JPEG support 60 | - Added support for EXIF and ICC data 61 | - Minimum supported rust version changed to 1.48 and no formal policy for bump releases for now 62 | - Minor stability fixes on invalid jpeg images 63 | 64 | ## v0.1.22 (2021-01-27) 65 | 66 | - Fix panic on jpeg without frames. 67 | 68 | ## v0.1.21 (2021-01-23) 69 | 70 | - Fix incorrect order of MCUs in non-interleaved streams 71 | - DCT Progressive images with incomplete coefficient blocks are now rendered 72 | - Fix a panic on invalid dimensions 73 | - Reduce allocations and runtime of decoding 74 | - Rework multi-threading to run a thread per component 75 | 76 | ## v0.1.20 (2020-07-04) 77 | 78 | - Fix decoding of some progressive images failing 79 | - Several more performance improvements 80 | - Add `PixelFormat::pixel_bytes` to determine the size of pixels 81 | - Cleanup and clarification of the 8x8 idct implementation 82 | - Updated fuzzing harnesses and helpers 83 | 84 | ## v0.1.19 (2020-04-27) 85 | - Fix decoding returning too much image data 86 | - Fix recognizing padding in marker segments 87 | - Several decode performance improvements 88 | - Remove use of deprecated `Error::description` 89 | 90 | ## v0.1.18 (2019-12-10) 91 | - Fix two bugs causing panics introduced in 0.1.17. 92 | 93 | ## v0.1.17 (2019-12-08) 94 | - Minimum supported rust version changed to 1.34 95 | - Fix clippy::into_iter_on_array warning 96 | - Ignore extraneous bytes after SOS 97 | - Support IDCT Scaling 98 | 99 | ## v0.1.16 (2019-08-25) 100 | - Minimum supported rust version changed to 1.28 101 | - Allow zero length DHT segments 102 | 103 | ## v0.1.15 (2018-06-10) 104 | - Added support for WebAssembly and asm.js (thanks @CryZe!) 105 | - Bugfix for images with APP14 segments longer than 12 bytes. 106 | 107 | ## v0.1.14 (2018-02-15) 108 | - Updated `rayon` to 1.0. 109 | 110 | ## v0.1.13 (2017-06-14) 111 | - Updated `rayon` to 0.8. 112 | 113 | ## v0.1.12 (2017-04-07) 114 | - Fixed an integer overflow in `derive_huffman_codes`. 115 | - Updated `rayon` to 0.7. 116 | 117 | ## v0.1.11 (2017-01-09) 118 | - Fixed an integer overflow. 119 | - Updated `byteorder` to 1.0. 120 | 121 | ## v0.1.10 (2016-12-23) 122 | - Updated `rayon` to 0.6 123 | 124 | ## v0.1.9 (2016-12-12) 125 | - Added a generic integer upsampler, which brings support for some unusual subsampling schemes, e.g. 4:1:1 (thanks @iamrohit7!) 126 | - Made rayon optional through the `rayon` cargo feature (thanks @jackpot51!) 127 | 128 | ## v0.1.8 (2016-11-05) 129 | * Updated rayon to version 0.5. 130 | 131 | ## v0.1.7 (2016-10-04) 132 | - Added `UnsupportedFeature::NonIntegerSubsamplingRatio` error 133 | - Fixed a bug which could cause certain images to fail decoding 134 | - Fixed decoding of JPEGs which has a final RST marker in their entropy-coded data 135 | - Avoid allocating coefficients when calling `read_info()` on progressive JPEGs 136 | 137 | ## v0.1.6 (2016-07-12) 138 | - Added support for 16-bit quantization tables (even though the JPEG spec explicitly 139 | states "An 8-bit DCT-based process shall not use a 16-bit precision quantization table", 140 | but since libjpeg allows it there is little choice...) 141 | - Added support for decoding files with extraneous data (this violates the JPEG spec, but libjpeg allows it) 142 | - Fixed panic when decoding files without SOF 143 | - Fixed bug which caused files with certain APP marker segments to fail decoding 144 | 145 | ## v0.1.5 (2016-06-22) 146 | - Removed `euclid` and `num-rational` dependencies 147 | - Updated `rayon` to 0.4 148 | 149 | ## v0.1.4 (2016-04-20) 150 | - Replaced `num` with `num-rational` 151 | 152 | ## v0.1.3 (2016-04-06) 153 | - Updated `byteorder` to 0.5 154 | 155 | ## v0.1.2 (2016-03-08) 156 | - Fixed a bug which was causing some progressive JPEGs to fail decoding 157 | - Performance improvements 158 | 159 | ## v0.1.1 (2016-02-29) 160 | - Performance improvements 161 | 162 | ## v0.1.0 (2016-02-13) 163 | - Initial release 164 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jpeg-decoder" 3 | version = "0.3.1" 4 | edition = "2021" 5 | 6 | rust-version = "1.61.0" 7 | 8 | license = "MIT OR Apache-2.0" 9 | description = "JPEG decoder" 10 | authors = ["The image-rs Developers"] 11 | readme = "README.md" 12 | 13 | documentation = "https://docs.rs/jpeg-decoder" 14 | repository = "https://github.com/image-rs/jpeg-decoder" 15 | keywords = ["jpeg", "jpg", "decoder", "image"] 16 | exclude = ["/tests/*", "!/tests/*.rs"] 17 | 18 | [dependencies] 19 | rayon = { version = "1.5.1", optional = true } 20 | 21 | [dev-dependencies] 22 | png = "0.16" 23 | walkdir = "2.0" 24 | criterion = "0.3" 25 | wasm-bindgen-test = "0.3" 26 | wasm-bindgen = "0.2.89" 27 | 28 | [features] 29 | default = ["rayon"] 30 | platform_independent = [] 31 | # Opt-in, this depends on Rust nightly. Will be changed to a no-op feature when 32 | # the Rust feature is stabilized which is expected to be 1.61. 33 | nightly_aarch64_neon = [] 34 | 35 | ## Internal development configuration: testing and benchmarking 36 | 37 | [[bench]] 38 | name = "decoding_benchmark" 39 | harness = false 40 | 41 | [[bench]] 42 | name = "large_image" 43 | harness = false 44 | 45 | [[test]] 46 | name = "rayon" 47 | required-features = ["rayon"] 48 | 49 | [[test]] 50 | name = "rayon-0" 51 | required-features = ["rayon"] 52 | 53 | [[test]] 54 | name = "rayon-1" 55 | required-features = ["rayon"] 56 | 57 | [[test]] 58 | name = "rayon-2" 59 | required-features = ["rayon"] 60 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 The jpeg-decoder Developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **WARNING: This crate is in maintenance mode as _image-rs_ seeks to move over to the zune-jpeg crate. However, since other Rust JPEG crates do not support lossless mode, we will continue to welcome PRs related to that functionality.** 2 | 3 | --- 4 | # jpeg-decoder 5 | 6 | [![Rust CI](https://github.com/image-rs/jpeg-decoder/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/jpeg-decoder/actions) 7 | [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/k65rrkd0f8yb4o9w/branch/master?svg=true)](https://ci.appveyor.com/project/kaksmet/jpeg-decoder/branch/master) 8 | [![crates.io](https://img.shields.io/crates/v/jpeg-decoder.svg)](https://crates.io/crates/jpeg-decoder) 9 | 10 | A Rust library for decoding JPEGs. 11 | 12 | [Documentation](https://docs.rs/jpeg-decoder) 13 | 14 | ## Example 15 | 16 | Cargo.toml: 17 | ```toml 18 | [dependencies] 19 | jpeg-decoder = "0.3" 20 | ``` 21 | 22 | main.rs: 23 | ```rust 24 | extern crate jpeg_decoder as jpeg; 25 | 26 | use std::fs::File; 27 | use std::io::BufReader; 28 | 29 | fn main() { 30 | let file = File::open("hello_world.jpg").expect("failed to open file"); 31 | let mut decoder = jpeg::Decoder::new(BufReader::new(file)); 32 | let pixels = decoder.decode().expect("failed to decode image"); 33 | let metadata = decoder.info().unwrap(); 34 | } 35 | ``` 36 | 37 | ## Requirements 38 | 39 | This crate compiles with Rust >= 1.61. Minimum supported Rust version: 40 | - All releases `0.1.*` compile with Rust >= 1.36. 41 | - All releases `0.2.*` compile with Rust >= 1.48. 42 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - TARGET: x86_64-pc-windows-msvc 4 | - TARGET: i686-pc-windows-msvc 5 | - TARGET: i686-pc-windows-gnu 6 | 7 | install: 8 | - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" 9 | - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" 10 | - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin 11 | - SET PATH=%PATH%;C:\MinGW\bin 12 | - rustc -V 13 | - cargo -V 14 | 15 | build: false 16 | 17 | test_script: 18 | - cargo build --verbose 19 | - cargo test --tests --benches 20 | - cargo bench --bench decoding_benchmark --no-default-features --features "$FEATURES" -- --warm-up-time 1 --measurement-time 1 --sample-size 25 21 | -------------------------------------------------------------------------------- /benches/decoding_benchmark.rs: -------------------------------------------------------------------------------- 1 | extern crate criterion; 2 | extern crate jpeg_decoder; 3 | 4 | use criterion::{black_box, Criterion}; 5 | 6 | use jpeg_decoder as jpeg; 7 | use jpeg_decoder::ImageInfo; 8 | 9 | fn read_image(image: &[u8]) -> Vec { 10 | jpeg::Decoder::new(black_box(image)).decode().unwrap() 11 | } 12 | 13 | fn read_metadata(image: &[u8]) -> ImageInfo { 14 | let mut decoder = jpeg::Decoder::new(black_box(image)); 15 | decoder.read_info().unwrap(); 16 | decoder.info().unwrap() 17 | } 18 | 19 | fn main() { 20 | let mut c = Criterion::default().configure_from_args(); 21 | c.bench_function("decode a 512x512 JPEG", |b| b.iter(|| { 22 | read_image(include_bytes!("tower.jpg")) 23 | })); 24 | 25 | c.bench_function("decode a 512x512 progressive JPEG", |b| b.iter(|| { 26 | read_image(include_bytes!("tower_progressive.jpg")) 27 | })); 28 | 29 | c.bench_function("decode a 512x512 grayscale JPEG", |b| b.iter(|| { 30 | read_image(include_bytes!("tower_grayscale.jpg")) 31 | })); 32 | 33 | c.bench_function("extract metadata from an image", |b| b.iter(|| { 34 | read_metadata(include_bytes!("tower.jpg")) 35 | })); 36 | 37 | c.bench_function("decode a 3072x2048 RGB Lossless JPEG", |b| b.iter(|| { 38 | read_image(include_bytes!("../tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.jpg")) 39 | })); 40 | c.final_summary(); 41 | } -------------------------------------------------------------------------------- /benches/large_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/benches/large_image.jpg -------------------------------------------------------------------------------- /benches/large_image.rs: -------------------------------------------------------------------------------- 1 | extern crate criterion; 2 | extern crate jpeg_decoder; 3 | 4 | use criterion::{black_box, Criterion}; 5 | 6 | use jpeg_decoder as jpeg; 7 | 8 | fn read_image(image: &[u8]) -> Vec { 9 | jpeg::Decoder::new(black_box(image)).decode().unwrap() 10 | } 11 | 12 | fn main() { 13 | let mut c = Criterion::default().configure_from_args(); 14 | c.bench_function("decode a 2268x1512 JPEG", |b| { 15 | b.iter(|| read_image(include_bytes!("large_image.jpg"))) 16 | }); 17 | c.final_summary(); 18 | } 19 | -------------------------------------------------------------------------------- /benches/tower.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/benches/tower.jpg -------------------------------------------------------------------------------- /benches/tower_grayscale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/benches/tower_grayscale.jpg -------------------------------------------------------------------------------- /benches/tower_progressive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/benches/tower_progressive.jpg -------------------------------------------------------------------------------- /examples/decode.rs: -------------------------------------------------------------------------------- 1 | extern crate jpeg_decoder as jpeg; 2 | extern crate png; 3 | 4 | use std::env; 5 | use std::fs::File; 6 | use std::io::{self, BufReader, Write}; 7 | use std::process; 8 | 9 | fn usage() -> ! { 10 | write!(io::stderr(), "usage: decode image.jpg image.png").unwrap(); 11 | process::exit(1) 12 | } 13 | 14 | fn main() { 15 | let mut args = env::args().skip(1); 16 | let input_path = args.next().unwrap_or_else(|| usage()); 17 | let output_path = args.next().unwrap_or_else(|| usage()); 18 | 19 | let input_file = File::open(input_path).expect("The specified input file could not be opened"); 20 | let mut decoder = jpeg::Decoder::new(BufReader::new(input_file)); 21 | let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder"); 22 | let info = decoder.info().unwrap(); 23 | 24 | eprintln!("{:?}", info); 25 | eprintln!("Exif: {}", decoder.exif_data().is_some()); 26 | eprintln!("XMP: {}", decoder.xmp_data().is_some()); 27 | eprintln!("ICC: {}", decoder.icc_profile().is_some()); 28 | 29 | let output_file = File::create(output_path).unwrap(); 30 | let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32); 31 | 32 | match info.pixel_format { 33 | jpeg::PixelFormat::L16 => { 34 | encoder.set_depth(png::BitDepth::Sixteen); 35 | encoder.set_color(png::ColorType::Grayscale); 36 | }, 37 | jpeg::PixelFormat::RGB24 => { 38 | encoder.set_depth(png::BitDepth::Eight); 39 | encoder.set_color(png::ColorType::RGB); 40 | }, 41 | jpeg::PixelFormat::CMYK32 => { 42 | data = cmyk_to_rgb(&mut data); 43 | encoder.set_depth(png::BitDepth::Eight); 44 | encoder.set_color(png::ColorType::RGB) 45 | }, 46 | jpeg::PixelFormat::L8 => { 47 | encoder.set_depth(png::BitDepth::Eight); 48 | encoder.set_color(png::ColorType::Grayscale); 49 | }, 50 | } 51 | 52 | encoder.write_header() 53 | .expect("writing png header failed") 54 | .write_image_data(&data) 55 | .expect("png encoding failed"); 56 | } 57 | 58 | fn cmyk_to_rgb(input: &[u8]) -> Vec { 59 | let size = input.len() - input.len() / 4; 60 | let mut output = Vec::with_capacity(size); 61 | 62 | for pixel in input.chunks(4) { 63 | let c = pixel[0] as f32 / 255.0; 64 | let m = pixel[1] as f32 / 255.0; 65 | let y = pixel[2] as f32 / 255.0; 66 | let k = pixel[3] as f32 / 255.0; 67 | 68 | // CMYK -> CMY 69 | let c = c * (1.0 - k) + k; 70 | let m = m * (1.0 - k) + k; 71 | let y = y * (1.0 - k) + k; 72 | 73 | // CMY -> RGB 74 | let r = (1.0 - c) * 255.0; 75 | let g = (1.0 - m) * 255.0; 76 | let b = (1.0 - y) * 255.0; 77 | 78 | output.push(r as u8); 79 | output.push(g as u8); 80 | output.push(b as u8); 81 | } 82 | 83 | output 84 | } 85 | -------------------------------------------------------------------------------- /fuzz-afl/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | out-*/ 3 | -------------------------------------------------------------------------------- /fuzz-afl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzz-target-jpeg-decoder" 3 | version = "0.1.0" 4 | authors = ["jpeg-decoder developers"] 5 | edition = "2018" 6 | 7 | [[bin]] 8 | name = "fuzz_decode" 9 | path = "src/fuzz_decode.rs" 10 | 11 | [[bin]] 12 | name = "reproduce_decode" 13 | path = "src/reproduce_decode.rs" 14 | 15 | [[bin]] 16 | name = "fuzz_info" 17 | path = "src/fuzz_info.rs" 18 | 19 | [[bin]] 20 | name = "reproduce_info" 21 | path = "src/reproduce_info.rs" 22 | 23 | [dependencies] 24 | afl = "0.8" 25 | jpeg-decoder = { path = "../" } 26 | -------------------------------------------------------------------------------- /fuzz-afl/README.md: -------------------------------------------------------------------------------- 1 | # Fuzzing harnesses 2 | 3 | ## Using the fuzzer 4 | 5 | Install afl: 6 | 7 | $ cargo install afl 8 | 9 | Build fuzz target: 10 | 11 | $ cargo afl build --release --bin fuzz_ 12 | 13 | Run afl: 14 | 15 | $ mkdir out/ 16 | $ cargo afl fuzz -i in/ -o out/ target/release/fuzz_ 17 | 18 | To reproduce a crash: 19 | 20 | $ cargo run --bin reproduce_ 21 | -------------------------------------------------------------------------------- /fuzz-afl/in/4x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/4x4.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/grass.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000006,src_000000,op_flip1,pos_3,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000006,src_000000,op_flip1,pos_3,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000023,src_000000,op_flip1,pos_21,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000023,src_000000,op_flip1,pos_21,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000034,src_000000,op_flip1,pos_159,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000034,src_000000,op_flip1,pos_159,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000046,src_000000,op_flip1,pos_164,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000046,src_000000,op_flip1,pos_164,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000056,src_000000,op_flip1,pos_166,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000056,src_000000,op_flip1,pos_166,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000071,src_000000,op_flip1,pos_172.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000071,src_000000,op_flip1,pos_172.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000081,src_000000,op_flip1,pos_181,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000081,src_000000,op_flip1,pos_181,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000170,src_000000,op_flip1,pos_307,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000170,src_000000,op_flip1,pos_307,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000182,src_000000,op_flip1,pos_503,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000182,src_000000,op_flip1,pos_503,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000186,src_000000,op_flip2,pos_21,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000186,src_000000,op_flip2,pos_21,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000195,src_000000,op_flip2,pos_167,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000195,src_000000,op_flip2,pos_167,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000202,src_000000,op_flip2,pos_178,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000202,src_000000,op_flip2,pos_178,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000223,src_000000,op_flip2,pos_503,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000223,src_000000,op_flip2,pos_503,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000224,src_000000,op_flip2,pos_299.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000224,src_000000,op_flip2,pos_299.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000227,src_000000,op_flip2,pos_503,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000227,src_000000,op_flip2,pos_503,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000305,src_000000,op_arith8,pos_295,val_+20,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000305,src_000000,op_arith8,pos_295,val_+20,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000324,src_000000,op_arith16,pos_227,val_be_-16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000324,src_000000,op_arith16,pos_227,val_be_-16.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000338,src_000000,op_int8,pos_23,val_+0,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000338,src_000000,op_int8,pos_23,val_+0,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000386,src_000000,op_havoc,rep_128,+cov.jpg: -------------------------------------------------------------------------------- 1 | � -------------------------------------------------------------------------------- /fuzz-afl/in/id_000393,src_000000,op_int32,pos_500,val_-32768,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000393,src_000000,op_int32,pos_500,val_-32768,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000397,src_000000,op_havoc,rep_64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000397,src_000000,op_havoc,rep_64.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000400,src_000000,op_havoc,rep_64,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000400,src_000000,op_havoc,rep_64,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000416,src_000000,op_havoc,rep_16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000416,src_000000,op_havoc,rep_16.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000448,src_000000,op_havoc,rep_32,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000448,src_000000,op_havoc,rep_32,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000449,src_000000,op_havoc,rep_16,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000449,src_000000,op_havoc,rep_16,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000508,src_000000,op_havoc,rep_16,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000508,src_000000,op_havoc,rep_16,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000514,src_000000,op_havoc,rep_16,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000514,src_000000,op_havoc,rep_16,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000514,src_000000,op_havoc,rep_32,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000514,src_000000,op_havoc,rep_32,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000528,src_000000,op_havoc,rep_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000528,src_000000,op_havoc,rep_8.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000568,src_000000,op_havoc,rep_8,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000568,src_000000,op_havoc,rep_8,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000578,src_000000,op_havoc,rep_8,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000578,src_000000,op_havoc,rep_8,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000594,sync_jpeg_turbo,src_000580.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000594,sync_jpeg_turbo,src_000580.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000597,sync_jpeg_turbo,src_000558.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000597,sync_jpeg_turbo,src_000558.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000647,src_000035,op_flip1,pos_305,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000647,src_000035,op_flip1,pos_305,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000667,src_000035,op_int16,pos_306,val_be_+32,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000667,src_000035,op_int16,pos_306,val_be_+32,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000681,src_000036,op_int8,pos_306,val_+1,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000681,src_000036,op_int8,pos_306,val_+1,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000687,sync_jpeg9,src_001936,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000687,sync_jpeg9,src_001936,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000827,sync_jpeg9,src_001156.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000827,sync_jpeg9,src_001156.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000831,sync_jpeg9,src_000903.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000831,sync_jpeg9,src_000903.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000838,sync_jpeg9,src_000485,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000838,sync_jpeg9,src_000485,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000885,sync_jpeg9,src_000654,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000885,sync_jpeg9,src_000654,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000903,src_000177,op_havoc,rep_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000903,src_000177,op_havoc,rep_2.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000961,sync_jpeg9,src_002802.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000961,sync_jpeg9,src_002802.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_000989,sync_jpeg9,src_001094.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_000989,sync_jpeg9,src_001094.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001085,sync_jpeg9,src_000887,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001085,sync_jpeg9,src_000887,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001086,sync_jpeg9,src_000744.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001086,sync_jpeg9,src_000744.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001118,sync_jpeg9,src_000623.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001118,sync_jpeg9,src_000623.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001136,sync_jpeg9,src_000760,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001136,sync_jpeg9,src_000760,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001156,sync_jpeg9,src_000847,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001156,sync_jpeg9,src_000847,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001211,sync_jpeg9,src_001184.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001211,sync_jpeg9,src_001184.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001259,sync_jpeg9,src_001469,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001259,sync_jpeg9,src_001469,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001265,sync_jpeg9,src_000512,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001265,sync_jpeg9,src_000512,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001346,sync_jpeg9,src_000740.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001346,sync_jpeg9,src_000740.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001366,sync_jpeg9,src_000537,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001366,sync_jpeg9,src_000537,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001386,src_000607,op_int32,pos_183,val_be_+1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001386,src_000607,op_int32,pos_183,val_be_+1.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001411,src_000636,op_flip4,pos_165,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001411,src_000636,op_flip4,pos_165,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001427,src_000319,op_havoc,rep_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001427,src_000319,op_havoc,rep_1.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001458,src_000531,op_flip4,pos_287.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001458,src_000531,op_flip4,pos_287.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001467,src_000666,op_flip4,pos_307,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001467,src_000666,op_flip4,pos_307,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001505,src_000633,op_flip1,pos_2,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001505,src_000633,op_flip1,pos_2,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001655,src_001333,op_flip2,pos_455.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001655,src_001333,op_flip2,pos_455.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001696,src_001527,op_arith8,pos_296,val_-17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001696,src_001527,op_arith8,pos_296,val_-17.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001744,src_001635,op_arith8,pos_164,val_-28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001744,src_001635,op_arith8,pos_164,val_-28.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001792,src_000728,op_int32,pos_227,val_be_+1000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001792,src_000728,op_int32,pos_227,val_be_+1000.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_001952,src_001930,op_havoc,rep_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_001952,src_001930,op_havoc,rep_4.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002005,src_001056,op_flip2,pos_175.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002005,src_001056,op_flip2,pos_175.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002075,src_001092,op_arith8,pos_209,val_+20,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002075,src_001092,op_arith8,pos_209,val_+20,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002199,sync_jpeg_turbo,src_001677.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002199,sync_jpeg_turbo,src_001677.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002306,src_001438,op_flip4,pos_290,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002306,src_001438,op_flip4,pos_290,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002423,src_001504,op_arith32,pos_300,val_-13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002423,src_001504,op_arith32,pos_300,val_-13.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_002987,sync_jpeg_turbo,src_001510,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_002987,sync_jpeg_turbo,src_001510,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003091,src_002994,op_flip1,pos_159,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003091,src_002994,op_flip1,pos_159,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003098,src_003010,op_flip4,pos_27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003098,src_003010,op_flip4,pos_27.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003112,src_003036,op_arith8,pos_175,val_+13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003112,src_003036,op_arith8,pos_175,val_+13.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003131,src_003114,op_havoc,rep_128,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003131,src_003114,op_havoc,rep_128,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003141,sync_jpeg_turbo,src_001694.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003141,sync_jpeg_turbo,src_001694.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003632,src_003613,op_havoc,rep_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003632,src_003613,op_havoc,rep_8.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003685,sync_jpeg_turbo,src_002052,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003685,sync_jpeg_turbo,src_002052,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_003813,sync_jpeg_turbo,src_002223.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_003813,sync_jpeg_turbo,src_002223.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004086,sync_jpeg_turbo,src_002441.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004086,sync_jpeg_turbo,src_002441.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004141,src_004138,op_int8,pos_44,val_+1,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004141,src_004138,op_int8,pos_44,val_+1,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004143,src_003886+004101,op_splice,rep_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004143,src_003886+004101,op_splice,rep_2.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004173,sync_jpeg_turbo,src_002577.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004173,sync_jpeg_turbo,src_002577.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004289,sync_jpeg_turbo,src_002582.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004289,sync_jpeg_turbo,src_002582.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004294,src_004289,op_flip2,pos_104.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004294,src_004289,op_flip2,pos_104.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004356,src_004355,op_flip1,pos_49.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004356,src_004355,op_flip1,pos_49.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004623,src_004596,op_havoc,rep_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004623,src_004596,op_havoc,rep_4.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004630,src_004598,op_arith8,pos_93,val_+9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004630,src_004598,op_arith8,pos_93,val_+9.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004675,src_004650,op_flip1,pos_103.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004675,src_004650,op_flip1,pos_103.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004829,sync_jpeg_turbo_extras,src_002309.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004829,sync_jpeg_turbo_extras,src_002309.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004851,sync_jpeg_turbo,src_003589.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004851,sync_jpeg_turbo,src_003589.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_004887,src_004848,op_flip1,pos_284.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_004887,src_004848,op_flip1,pos_284.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005371,src_004601,op_havoc,rep_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005371,src_004601,op_havoc,rep_2.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005661,src_005658,op_havoc,rep_8,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005661,src_005658,op_havoc,rep_8,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005679,src_005671,op_havoc,rep_1,+cov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005679,src_005671,op_havoc,rep_1,+cov.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005745,src_005744,op_flip1,pos_97.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005745,src_005744,op_flip1,pos_97.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005758,sync_jpeg_turbo,src_004354.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005758,sync_jpeg_turbo,src_004354.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/id_005761,src_005759,op_flip1,pos_52.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/id_005761,src_005759,op_flip1,pos_52.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/relax-jpeg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/relax-jpeg.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/relax-jpeg2000.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/relax-jpeg2000.jp2 -------------------------------------------------------------------------------- /fuzz-afl/in/window-q0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/window-q0.jpg -------------------------------------------------------------------------------- /fuzz-afl/in/window-q20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/fuzz-afl/in/window-q20.jpg -------------------------------------------------------------------------------- /fuzz-afl/src/fuzz_decode.rs: -------------------------------------------------------------------------------- 1 | use afl::fuzz; 2 | 3 | use jpeg_decoder::{Decoder, Error}; 4 | 5 | #[inline(always)] 6 | fn decode(data: &[u8]) -> Result, Error> { 7 | let mut decoder = Decoder::new(data); 8 | decoder.decode() 9 | } 10 | 11 | fn main() { 12 | fuzz(true, |data: &[u8]| { 13 | let _ = decode(data); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /fuzz-afl/src/fuzz_info.rs: -------------------------------------------------------------------------------- 1 | use afl::fuzz; 2 | 3 | use jpeg_decoder::{Decoder, ImageInfo}; 4 | 5 | #[inline(always)] 6 | fn get_info(data: &[u8]) -> Option { 7 | let mut decoder = Decoder::new(data); 8 | decoder.read_info().ok().and_then(|_| decoder.info()) 9 | } 10 | 11 | fn main() { 12 | fuzz(true, |data: &[u8]| { 13 | let _ = get_info(data); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /fuzz-afl/src/reproduce_decode.rs: -------------------------------------------------------------------------------- 1 | use jpeg_decoder::{Decoder, Error}; 2 | 3 | mod utils; 4 | 5 | #[inline(always)] 6 | fn decode(data: &[u8]) -> Result, Error> { 7 | let mut decoder = Decoder::new(data); 8 | decoder.decode() 9 | } 10 | 11 | fn main() { 12 | let data = utils::read_file_from_args(); 13 | match decode(&data) { 14 | Ok(bytes) => println!("Decoded {} bytes", bytes.len()), 15 | Err(e) => println!("Decoder returned an error: {e:?}\nNote: Not a panic, this is fine."), 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /fuzz-afl/src/reproduce_info.rs: -------------------------------------------------------------------------------- 1 | use jpeg_decoder::{Decoder, ImageInfo}; 2 | 3 | mod utils; 4 | 5 | #[inline(always)] 6 | fn get_info(data: &[u8]) -> Option { 7 | let mut decoder = Decoder::new(data); 8 | decoder.read_info().ok().and_then(|_| decoder.info()) 9 | } 10 | 11 | fn main() { 12 | let data = utils::read_file_from_args(); 13 | match get_info(&data) { 14 | Some(info) => println!("Info: {:?}", info), 15 | None => println!("Found no info in file"), 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /fuzz-afl/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn read_file_from_args() -> Vec { 2 | let args: Vec = std::env::args().collect(); 3 | if args.len() != 2 { 4 | println!("Usage: {} ", args[0]); 5 | std::process::exit(1); 6 | } 7 | let data = std::fs::read(&args[1]) 8 | .expect(&format!("Could not open file {}", args[1])); 9 | data 10 | } 11 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "jpeg-decoder-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.3" 14 | 15 | [dependencies.jpeg-decoder] 16 | path = ".." 17 | 18 | [dependencies.previous] 19 | package = "jpeg-decoder" 20 | git = "https://github.com/image-rs/jpeg-decoder" 21 | 22 | [dependencies.image] 23 | version = "0.23.4" 24 | default-features = false 25 | features = ["pnm"] 26 | 27 | [dependencies.mozjpeg] 28 | version = "0.8.17" 29 | 30 | # Prevent this from interfering with workspaces 31 | [workspace] 32 | members = ["."] 33 | 34 | [[bin]] 35 | # A target with which we can minimize decoding failures. 36 | name = "fail_tmin" 37 | path = "fuzz_targets/fail_tmin.rs" 38 | test = false 39 | doc = false 40 | 41 | [[bin]] 42 | # A target to find regression test 43 | name = "regression" 44 | path = "fuzz_targets/regression.rs" 45 | test = false 46 | doc = false 47 | -------------------------------------------------------------------------------- /fuzz/Readme.md: -------------------------------------------------------------------------------- 1 | ## Regression test case minimization 2 | 3 | One of the targets is meant to minimize decoding failure regression tests. It 4 | relies on comparing the output of the local decoder against the version on 5 | Github's default branch. One of the goals is to remove copyrighted content from 6 | a reproduction case as well. 7 | 8 | ```bash 9 | cargo +nightly fuzz tmin regression known_reported_reproduction.jpeg 10 | ``` 11 | 12 | ## Reftest generation 13 | 14 | The second fuzzing target will help you generate an image for reftest. It 15 | relies on `mozjpeg` to keep the image correct while ensuring that a) the 16 | previous decoder failed and b) the current decoder succeeds and agrees with the 17 | output of `mozjpeg`. This is typically a tedious process so you'll need a lot 18 | of runs but the lib is really fast as everything happens in process. 19 | Unfortunately, it is also quite finicky as the color treatment is not the same 20 | with some deviation and seemingly `mozjpeg` is quite strict in what it accepts. 21 | You may need to manually edit the file structure and rely on this only for 22 | filling in some colors and index bytes that work. 23 | 24 | To work, create a new folder, copy a known minimized regression test case in 25 | and let it go to work. You might want to supply some other jpeg samples for 26 | convenience. 27 | 28 | ```bash 29 | tmpdir="$(mktemp)" 30 | cp -t "$tmpdir" minimized_reproduction.jpg 31 | cargo +nightly fuzz run fail_tmin "$tmpdir" 32 | ``` 33 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/fail_tmin.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | use std::io::{Error, Read, Write}; 4 | use std::process::{Command, Stdio}; 5 | 6 | use jpeg_decoder::Decoder; 7 | use image::ImageDecoder; 8 | use mozjpeg::decompress::Decompress; 9 | 10 | // Try to check the image, never panic. 11 | fn soft_check(data: &[u8]) -> Result, Error> { 12 | let decompress = Decompress::new_mem(data)?; 13 | let mut rgb = decompress.rgb()?; 14 | // Yikes. That method is unsound. But we don't care, we just don't use it with UB. 15 | let lines = rgb.read_scanlines::<[u8; 3]>() 16 | .ok_or_else(|| Error::from(std::io::ErrorKind::Other))?; 17 | let lines = unsafe { 18 | core::slice::from_raw_parts( 19 | lines.as_ptr() as *const u8, 20 | lines.len()*3) 21 | }.to_owned(); 22 | Ok(lines) 23 | } 24 | 25 | fn roughly(data: &[u8], reference: &[u8]) -> bool { 26 | data.len() == reference.len() && data 27 | .iter() 28 | .zip(reference) 29 | .all(|(&o, &r)| { 30 | // Not the same criterion as in ref test. For some reason, mozjpeg disagrees with both 31 | // our output _and_ the output of djpeg/libjpeg-turbo. Let's not question this too 32 | // much. 33 | (o as i16 - r as i16).abs() <= 3 34 | }) 35 | } 36 | 37 | fuzz_target!(|data: &[u8]| { 38 | let mut decoder = previous::Decoder::new(data); 39 | let wrong = decoder.decode().ok(); 40 | 41 | // The case should now be fixed. 42 | let ours = match Decoder::new(data).decode() { 43 | Err(_) => return, 44 | Ok(ours) => ours, 45 | }; 46 | 47 | // It should decode correctly. 48 | let reference = match soft_check(data) { 49 | Err(_) => return, // Don't crash if it's not a jpeg. 50 | Ok(reference) => reference, 51 | }; 52 | 53 | let _ = std::fs::write("/tmp/reference", &reference); 54 | let _ = std::fs::write("/tmp/ours", &ours); 55 | 56 | // It must now pass the reftest 57 | if !roughly(&ours, &reference) { 58 | return; 59 | } 60 | 61 | // The case must have previously failed to decode, or failed reftest 62 | match wrong { 63 | Some(data) if roughly(&data, &reference) => return, 64 | _ => {}, 65 | } 66 | 67 | panic!("Success") 68 | }); 69 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/regression.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use jpeg_decoder; 5 | use previous; 6 | 7 | fuzz_target!(|data: &[u8]| { 8 | // The case should now be fixed. 9 | match jpeg_decoder::Decoder::new(data).decode() { 10 | Err(_) => return, 11 | Ok(_) => {}, 12 | } 13 | 14 | // And error/fail on previous. 15 | match previous::Decoder::new(data).decode() { 16 | Ok(_) => return, 17 | Err(_) => panic!(), 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | 1.61.0 2 | -------------------------------------------------------------------------------- /src/arch/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(unsafe_code)] 2 | 3 | mod neon; 4 | mod ssse3; 5 | mod wasm; 6 | 7 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 8 | use std::is_x86_feature_detected; 9 | 10 | /// Arch-specific implementation of YCbCr conversion. Returns the number of pixels that were 11 | /// converted. 12 | #[allow(clippy::type_complexity)] 13 | pub fn get_color_convert_line_ycbcr() -> Option usize> 14 | { 15 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 16 | #[allow(unsafe_code)] 17 | { 18 | if is_x86_feature_detected!("ssse3") { 19 | return Some(ssse3::color_convert_line_ycbcr); 20 | } 21 | } 22 | // Runtime detection is not needed on aarch64. 23 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 24 | { 25 | return Some(neon::color_convert_line_ycbcr); 26 | } 27 | #[cfg(all(target_feature = "simd128", target_arch = "wasm32"))] 28 | { 29 | return Some(wasm::color_convert_line_ycbcr); 30 | } 31 | #[allow(unreachable_code)] 32 | None 33 | } 34 | 35 | /// Arch-specific implementation of 8x8 IDCT. 36 | #[allow(clippy::type_complexity)] 37 | pub fn get_dequantize_and_idct_block_8x8( 38 | ) -> Option { 39 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 40 | #[allow(unsafe_code)] 41 | { 42 | if is_x86_feature_detected!("ssse3") { 43 | return Some(ssse3::dequantize_and_idct_block_8x8); 44 | } 45 | } 46 | // Runtime detection is not needed on aarch64. 47 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 48 | { 49 | return Some(neon::dequantize_and_idct_block_8x8); 50 | } 51 | #[cfg(all(target_feature = "simd128", target_arch = "wasm32"))] 52 | { 53 | return Some(wasm::dequantize_and_idct_block_8x8); 54 | } 55 | #[allow(unreachable_code)] 56 | None 57 | } 58 | -------------------------------------------------------------------------------- /src/arch/neon.rs: -------------------------------------------------------------------------------- 1 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 2 | use core::arch::aarch64::*; 3 | 4 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 5 | #[target_feature(enable = "neon")] 6 | unsafe fn idct8(data: &mut [int16x8_t; 8]) { 7 | // The fixed-point constants here are obtained by taking the fractional part of the constants 8 | // from the non-SIMD implementation and scaling them up by 1<<15. This is because 9 | // vqrdmulhq_n_s16(a, b) is effectively equivalent to (a*b)>>15 (except for possibly some 10 | // slight differences in rounding). 11 | 12 | // The code here is effectively equivalent to the calls to "kernel" in idct.rs, except that it 13 | // doesn't apply any further scaling and fixed point constants have a different precision. 14 | 15 | let p2 = data[2]; 16 | let p3 = data[6]; 17 | let p1 = vqrdmulhq_n_s16(vqaddq_s16(p2, p3), 17734); // 0.5411961 18 | let t2 = vqsubq_s16( 19 | vqsubq_s16(p1, p3), 20 | vqrdmulhq_n_s16(p3, 27779), // 0.847759065 21 | ); 22 | let t3 = vqaddq_s16(p1, vqrdmulhq_n_s16(p2, 25079)); // 0.765366865 23 | 24 | let p2 = data[0]; 25 | let p3 = data[4]; 26 | let t0 = vqaddq_s16(p2, p3); 27 | let t1 = vqsubq_s16(p2, p3); 28 | 29 | let x0 = vqaddq_s16(t0, t3); 30 | let x3 = vqsubq_s16(t0, t3); 31 | let x1 = vqaddq_s16(t1, t2); 32 | let x2 = vqsubq_s16(t1, t2); 33 | 34 | let t0 = data[7]; 35 | let t1 = data[5]; 36 | let t2 = data[3]; 37 | let t3 = data[1]; 38 | 39 | let p3 = vqaddq_s16(t0, t2); 40 | let p4 = vqaddq_s16(t1, t3); 41 | let p1 = vqaddq_s16(t0, t3); 42 | let p2 = vqaddq_s16(t1, t2); 43 | let p5 = vqaddq_s16(p3, p4); 44 | let p5 = vqaddq_s16(p5, vqrdmulhq_n_s16(p5, 5763)); // 0.175875602 45 | 46 | let t0 = vqrdmulhq_n_s16(t0, 9786); // 0.298631336 47 | let t1 = vqaddq_s16( 48 | vqaddq_s16(t1, t1), 49 | vqrdmulhq_n_s16(t1, 1741), // 0.053119869 50 | ); 51 | let t2 = vqaddq_s16( 52 | vqaddq_s16(t2, vqaddq_s16(t2, t2)), 53 | vqrdmulhq_n_s16(t2, 2383), // 0.072711026 54 | ); 55 | let t3 = vqaddq_s16(t3, vqrdmulhq_n_s16(t3, 16427)); // 0.501321110 56 | 57 | let p1 = vqsubq_s16(p5, vqrdmulhq_n_s16(p1, 29490)); // 0.899976223 58 | let p2 = vqsubq_s16( 59 | vqsubq_s16(vqsubq_s16(p5, p2), p2), 60 | vqrdmulhq_n_s16(p2, 18446), // 0.562915447 61 | ); 62 | 63 | let p3 = vqsubq_s16( 64 | vqrdmulhq_n_s16(p3, -31509), // -0.961570560 65 | p3, 66 | ); 67 | let p4 = vqrdmulhq_n_s16(p4, -12785); // -0.390180644 68 | 69 | let t3 = vqaddq_s16(vqaddq_s16(p1, p4), t3); 70 | let t2 = vqaddq_s16(vqaddq_s16(p2, p3), t2); 71 | let t1 = vqaddq_s16(vqaddq_s16(p2, p4), t1); 72 | let t0 = vqaddq_s16(vqaddq_s16(p1, p3), t0); 73 | 74 | data[0] = vqaddq_s16(x0, t3); 75 | data[7] = vqsubq_s16(x0, t3); 76 | data[1] = vqaddq_s16(x1, t2); 77 | data[6] = vqsubq_s16(x1, t2); 78 | data[2] = vqaddq_s16(x2, t1); 79 | data[5] = vqsubq_s16(x2, t1); 80 | data[3] = vqaddq_s16(x3, t0); 81 | data[4] = vqsubq_s16(x3, t0); 82 | } 83 | 84 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 85 | #[target_feature(enable = "neon")] 86 | unsafe fn transpose8(data: &mut [int16x8_t; 8]) { 87 | // Use NEON's 2x2 matrix transposes (vtrn) to do the transposition in each 4x4 block, then 88 | // combine the 4x4 blocks. 89 | let a01 = vtrnq_s16(data[0], data[1]); 90 | let a23 = vtrnq_s16(data[2], data[3]); 91 | 92 | let four0 = vtrnq_s32(vreinterpretq_s32_s16(a01.0), vreinterpretq_s32_s16(a23.0)); 93 | let four1 = vtrnq_s32(vreinterpretq_s32_s16(a01.1), vreinterpretq_s32_s16(a23.1)); 94 | 95 | let a45 = vtrnq_s16(data[4], data[5]); 96 | let a67 = vtrnq_s16(data[6], data[7]); 97 | 98 | let four2 = vtrnq_s32(vreinterpretq_s32_s16(a45.0), vreinterpretq_s32_s16(a67.0)); 99 | let four3 = vtrnq_s32(vreinterpretq_s32_s16(a45.1), vreinterpretq_s32_s16(a67.1)); 100 | 101 | data[0] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four0.0), vget_low_s32(four2.0))); 102 | data[1] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four1.0), vget_low_s32(four3.0))); 103 | data[2] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four0.1), vget_low_s32(four2.1))); 104 | data[3] = vreinterpretq_s16_s32(vcombine_s32(vget_low_s32(four1.1), vget_low_s32(four3.1))); 105 | data[4] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four0.0), vget_high_s32(four2.0))); 106 | data[5] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four1.0), vget_high_s32(four3.0))); 107 | data[6] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four0.1), vget_high_s32(four2.1))); 108 | data[7] = vreinterpretq_s16_s32(vcombine_s32(vget_high_s32(four1.1), vget_high_s32(four3.1))); 109 | } 110 | 111 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 112 | #[target_feature(enable = "neon")] 113 | pub unsafe fn dequantize_and_idct_block_8x8( 114 | coefficients: &[i16; 64], 115 | quantization_table: &[u16; 64], 116 | output_linestride: usize, 117 | output: &mut [u8], 118 | ) { 119 | // The loop below will write to positions [output_linestride * i, output_linestride * i + 8) 120 | // for 0<=i<8. Thus, the last accessed position is at an offset of output_linestrade * 7 + 7, 121 | // and if that position is in-bounds, so are all other accesses. 122 | assert!( 123 | output.len() 124 | > output_linestride 125 | .checked_mul(7) 126 | .unwrap() 127 | .checked_add(7) 128 | .unwrap() 129 | ); 130 | 131 | const SHIFT: i32 = 3; 132 | 133 | // Read the DCT coefficients, scale them up and dequantize them. 134 | let mut data = [vdupq_n_s16(0); 8]; 135 | for i in 0..8 { 136 | data[i] = vshlq_n_s16( 137 | vmulq_s16( 138 | vld1q_s16(coefficients.as_ptr().wrapping_add(i * 8)), 139 | vreinterpretq_s16_u16(vld1q_u16(quantization_table.as_ptr().wrapping_add(i * 8))), 140 | ), 141 | SHIFT, 142 | ); 143 | } 144 | 145 | // Usual column IDCT - transpose - column IDCT - transpose approach. 146 | idct8(&mut data); 147 | transpose8(&mut data); 148 | idct8(&mut data); 149 | transpose8(&mut data); 150 | 151 | for i in 0..8 { 152 | // The two passes of the IDCT algorithm give us a factor of 8, so the shift here is 153 | // increased by 3. 154 | // As values will be stored in a u8, they need to be 128-centered and not 0-centered. 155 | // We add 128 with the appropriate shift for that purpose. 156 | const OFFSET: i16 = 128 << (SHIFT + 3); 157 | // We want rounding right shift, so we should add (1/2) << (SHIFT+3) before shifting. 158 | const ROUNDING_BIAS: i16 = (1 << (SHIFT + 3)) >> 1; 159 | 160 | let data_with_offset = vqaddq_s16(data[i], vdupq_n_s16(OFFSET + ROUNDING_BIAS)); 161 | 162 | vst1_u8( 163 | output.as_mut_ptr().wrapping_add(output_linestride * i), 164 | vqshrun_n_s16(data_with_offset, SHIFT + 3), 165 | ); 166 | } 167 | } 168 | 169 | #[cfg(all(feature = "nightly_aarch64_neon", target_arch = "aarch64"))] 170 | #[target_feature(enable = "neon")] 171 | pub unsafe fn color_convert_line_ycbcr(y: &[u8], cb: &[u8], cr: &[u8], output: &mut [u8]) -> usize { 172 | assert!(output.len() % 3 == 0); 173 | let num = output.len() / 3; 174 | assert!(num <= y.len()); 175 | assert!(num <= cb.len()); 176 | assert!(num <= cr.len()); 177 | let num_vecs = num / 8; 178 | 179 | for i in 0..num_vecs { 180 | const SHIFT: i32 = 6; 181 | // Load. 182 | let y = vld1_u8(y.as_ptr().wrapping_add(i * 8)); 183 | let cb = vld1_u8(cb.as_ptr().wrapping_add(i * 8)); 184 | let cr = vld1_u8(cr.as_ptr().wrapping_add(i * 8)); 185 | 186 | // Convert to 16 bit and shift. 187 | let y = vreinterpretq_s16_u16(vshll_n_u8(y, SHIFT)); 188 | let cb = vreinterpretq_s16_u16(vshll_n_u8(cb, SHIFT)); 189 | let cr = vreinterpretq_s16_u16(vshll_n_u8(cr, SHIFT)); 190 | 191 | // Add offsets 192 | let y = vqaddq_s16(y, vdupq_n_s16((1 << SHIFT) >> 1)); 193 | let c128 = vdupq_n_s16(128 << SHIFT); 194 | let cb = vqsubq_s16(cb, c128); 195 | let cr = vqsubq_s16(cr, c128); 196 | 197 | // Compute cr * 1.402, cb * 0.34414, cr * 0.71414, cb * 1.772 198 | let cr_140200 = vqaddq_s16(vqrdmulhq_n_s16(cr, 13173), cr); 199 | let cb_034414 = vqrdmulhq_n_s16(cb, 11276); 200 | let cr_071414 = vqrdmulhq_n_s16(cr, 23401); 201 | let cb_177200 = vqaddq_s16(vqrdmulhq_n_s16(cb, 25297), cb); 202 | 203 | // Last conversion step. 204 | let r = vqaddq_s16(y, cr_140200); 205 | let g = vqsubq_s16(y, vqaddq_s16(cb_034414, cr_071414)); 206 | let b = vqaddq_s16(y, cb_177200); 207 | 208 | // Shift back and convert to u8. 209 | let r = vqshrun_n_s16(r, SHIFT); 210 | let g = vqshrun_n_s16(g, SHIFT); 211 | let b = vqshrun_n_s16(b, SHIFT); 212 | 213 | // Shuffle + store. 214 | vst3_u8( 215 | output.as_mut_ptr().wrapping_add(24 * i), 216 | uint8x8x3_t(r, g, b), 217 | ); 218 | } 219 | 220 | num_vecs * 8 221 | } 222 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use alloc::fmt; 3 | use alloc::string::String; 4 | use core::result; 5 | use std::error::Error as StdError; 6 | use std::io::Error as IoError; 7 | 8 | use crate::ColorTransform; 9 | 10 | pub type Result = result::Result; 11 | 12 | /// An enumeration over JPEG features (currently) unsupported by this library. 13 | /// 14 | /// Support for features listed here may be included in future versions of this library. 15 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 16 | pub enum UnsupportedFeature { 17 | /// Hierarchical JPEG. 18 | Hierarchical, 19 | /// JPEG using arithmetic entropy coding instead of Huffman coding. 20 | ArithmeticEntropyCoding, 21 | /// Sample precision in bits. 8 bit sample precision is what is currently supported in non-lossless coding process. 22 | SamplePrecision(u8), 23 | /// Number of components in an image. 1, 3 and 4 components are currently supported. 24 | ComponentCount(u8), 25 | /// An image can specify a zero height in the frame header and use the DNL (Define Number of 26 | /// Lines) marker at the end of the first scan to define the number of lines in the frame. 27 | DNL, 28 | /// Subsampling ratio. 29 | SubsamplingRatio, 30 | /// A subsampling ratio not representable as an integer. 31 | NonIntegerSubsamplingRatio, 32 | /// Colour transform 33 | ColorTransform(ColorTransform), 34 | } 35 | 36 | /// Errors that can occur while decoding a JPEG image. 37 | #[derive(Debug)] 38 | pub enum Error { 39 | /// The image is not formatted properly. The string contains detailed information about the 40 | /// error. 41 | Format(String), 42 | /// The image makes use of a JPEG feature not (currently) supported by this library. 43 | Unsupported(UnsupportedFeature), 44 | /// An I/O error occurred while decoding the image. 45 | Io(IoError), 46 | /// An internal error occurred while decoding the image. 47 | Internal(Box), //TODO: not used, can be removed with the next version bump 48 | } 49 | 50 | impl fmt::Display for Error { 51 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 52 | match *self { 53 | Error::Format(ref desc) => write!(f, "invalid JPEG format: {}", desc), 54 | Error::Unsupported(ref feat) => write!(f, "unsupported JPEG feature: {:?}", feat), 55 | Error::Io(ref err) => err.fmt(f), 56 | Error::Internal(ref err) => err.fmt(f), 57 | } 58 | } 59 | } 60 | 61 | impl StdError for Error { 62 | fn source(&self) -> Option<&(dyn StdError + 'static)> { 63 | match *self { 64 | Error::Io(ref err) => Some(err), 65 | Error::Internal(ref err) => Some(&**err), 66 | _ => None, 67 | } 68 | } 69 | } 70 | 71 | impl From for Error { 72 | fn from(err: IoError) -> Error { 73 | Error::Io(err) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate contains a JPEG decoder. 2 | //! 3 | //! # Examples 4 | //! 5 | //! ``` 6 | //! use jpeg_decoder::Decoder; 7 | //! use std::fs::File; 8 | //! use std::io::BufReader; 9 | //! 10 | //! let file = File::open("tests/reftest/images/extraneous-data.jpg").expect("failed to open file"); 11 | //! let mut decoder = Decoder::new(BufReader::new(file)); 12 | //! let pixels = decoder.decode().expect("failed to decode image"); 13 | //! let metadata = decoder.info().unwrap(); 14 | //! ``` 15 | //! 16 | //! Get metadata from a file without decoding it: 17 | //! 18 | //! ``` 19 | //! use jpeg_decoder::Decoder; 20 | //! use std::fs::File; 21 | //! use std::io::BufReader; 22 | //! 23 | //! let file = File::open("tests/reftest/images/extraneous-data.jpg").expect("failed to open file"); 24 | //! let mut decoder = Decoder::new(BufReader::new(file)); 25 | //! decoder.read_info().expect("failed to read metadata"); 26 | //! let metadata = decoder.info().unwrap(); 27 | //! ``` 28 | 29 | #![deny(missing_docs)] 30 | #![deny(unsafe_code)] 31 | #![cfg_attr(feature = "platform_independent", forbid(unsafe_code))] 32 | 33 | extern crate alloc; 34 | extern crate core; 35 | 36 | #[cfg(feature = "rayon")] 37 | extern crate rayon; 38 | 39 | pub use decoder::{ColorTransform, Decoder, ImageInfo, PixelFormat}; 40 | pub use error::{Error, UnsupportedFeature}; 41 | pub use parser::CodingProcess; 42 | 43 | use std::io; 44 | 45 | #[cfg(not(feature = "platform_independent"))] 46 | mod arch; 47 | mod decoder; 48 | mod error; 49 | mod huffman; 50 | mod idct; 51 | mod marker; 52 | mod parser; 53 | mod upsampler; 54 | mod worker; 55 | 56 | fn read_u8(reader: &mut R) -> io::Result { 57 | let mut buf = [0]; 58 | reader.read_exact(&mut buf)?; 59 | Ok(buf[0]) 60 | } 61 | 62 | fn read_u16_from_be(reader: &mut R) -> io::Result { 63 | let mut buf = [0, 0]; 64 | reader.read_exact(&mut buf)?; 65 | Ok(u16::from_be_bytes(buf)) 66 | } 67 | -------------------------------------------------------------------------------- /src/marker.rs: -------------------------------------------------------------------------------- 1 | // Table B.1 2 | #[derive(Clone, Copy, Debug, PartialEq)] 3 | // Note: Established names. 4 | #[allow(clippy::upper_case_acronyms)] 5 | pub enum Marker { 6 | /// Start Of Frame markers 7 | /// 8 | /// - SOF(0): Baseline DCT (Huffman coding) 9 | /// - SOF(1): Extended sequential DCT (Huffman coding) 10 | /// - SOF(2): Progressive DCT (Huffman coding) 11 | /// - SOF(3): Lossless (sequential) (Huffman coding) 12 | /// - SOF(5): Differential sequential DCT (Huffman coding) 13 | /// - SOF(6): Differential progressive DCT (Huffman coding) 14 | /// - SOF(7): Differential lossless (sequential) (Huffman coding) 15 | /// - SOF(9): Extended sequential DCT (arithmetic coding) 16 | /// - SOF(10): Progressive DCT (arithmetic coding) 17 | /// - SOF(11): Lossless (sequential) (arithmetic coding) 18 | /// - SOF(13): Differential sequential DCT (arithmetic coding) 19 | /// - SOF(14): Differential progressive DCT (arithmetic coding) 20 | /// - SOF(15): Differential lossless (sequential) (arithmetic coding) 21 | SOF(u8), 22 | /// Reserved for JPEG extensions 23 | JPG, 24 | /// Define Huffman table(s) 25 | DHT, 26 | /// Define arithmetic coding conditioning(s) 27 | DAC, 28 | /// Restart with modulo 8 count `m` 29 | RST(u8), 30 | /// Start of image 31 | SOI, 32 | /// End of image 33 | EOI, 34 | /// Start of scan 35 | SOS, 36 | /// Define quantization table(s) 37 | DQT, 38 | /// Define number of lines 39 | DNL, 40 | /// Define restart interval 41 | DRI, 42 | /// Define hierarchical progression 43 | DHP, 44 | /// Expand reference component(s) 45 | EXP, 46 | /// Reserved for application segments 47 | APP(u8), 48 | /// Reserved for JPEG extensions 49 | JPGn(u8), 50 | /// Comment 51 | COM, 52 | /// For temporary private use in arithmetic coding 53 | TEM, 54 | /// Reserved 55 | RES, 56 | } 57 | 58 | impl Marker { 59 | pub fn has_length(self) -> bool { 60 | use self::Marker::*; 61 | ! matches!(self, RST(..) | SOI | EOI | TEM) 62 | } 63 | 64 | pub fn from_u8(n: u8) -> Option { 65 | use self::Marker::*; 66 | match n { 67 | 0x00 => None, // Byte stuffing 68 | 0x01 => Some(TEM), 69 | 0x02 ..= 0xBF => Some(RES), 70 | 0xC0 => Some(SOF(0)), 71 | 0xC1 => Some(SOF(1)), 72 | 0xC2 => Some(SOF(2)), 73 | 0xC3 => Some(SOF(3)), 74 | 0xC4 => Some(DHT), 75 | 0xC5 => Some(SOF(5)), 76 | 0xC6 => Some(SOF(6)), 77 | 0xC7 => Some(SOF(7)), 78 | 0xC8 => Some(JPG), 79 | 0xC9 => Some(SOF(9)), 80 | 0xCA => Some(SOF(10)), 81 | 0xCB => Some(SOF(11)), 82 | 0xCC => Some(DAC), 83 | 0xCD => Some(SOF(13)), 84 | 0xCE => Some(SOF(14)), 85 | 0xCF => Some(SOF(15)), 86 | 0xD0 => Some(RST(0)), 87 | 0xD1 => Some(RST(1)), 88 | 0xD2 => Some(RST(2)), 89 | 0xD3 => Some(RST(3)), 90 | 0xD4 => Some(RST(4)), 91 | 0xD5 => Some(RST(5)), 92 | 0xD6 => Some(RST(6)), 93 | 0xD7 => Some(RST(7)), 94 | 0xD8 => Some(SOI), 95 | 0xD9 => Some(EOI), 96 | 0xDA => Some(SOS), 97 | 0xDB => Some(DQT), 98 | 0xDC => Some(DNL), 99 | 0xDD => Some(DRI), 100 | 0xDE => Some(DHP), 101 | 0xDF => Some(EXP), 102 | 0xE0 => Some(APP(0)), 103 | 0xE1 => Some(APP(1)), 104 | 0xE2 => Some(APP(2)), 105 | 0xE3 => Some(APP(3)), 106 | 0xE4 => Some(APP(4)), 107 | 0xE5 => Some(APP(5)), 108 | 0xE6 => Some(APP(6)), 109 | 0xE7 => Some(APP(7)), 110 | 0xE8 => Some(APP(8)), 111 | 0xE9 => Some(APP(9)), 112 | 0xEA => Some(APP(10)), 113 | 0xEB => Some(APP(11)), 114 | 0xEC => Some(APP(12)), 115 | 0xED => Some(APP(13)), 116 | 0xEE => Some(APP(14)), 117 | 0xEF => Some(APP(15)), 118 | 0xF0 => Some(JPGn(0)), 119 | 0xF1 => Some(JPGn(1)), 120 | 0xF2 => Some(JPGn(2)), 121 | 0xF3 => Some(JPGn(3)), 122 | 0xF4 => Some(JPGn(4)), 123 | 0xF5 => Some(JPGn(5)), 124 | 0xF6 => Some(JPGn(6)), 125 | 0xF7 => Some(JPGn(7)), 126 | 0xF8 => Some(JPGn(8)), 127 | 0xF9 => Some(JPGn(9)), 128 | 0xFA => Some(JPGn(10)), 129 | 0xFB => Some(JPGn(11)), 130 | 0xFC => Some(JPGn(12)), 131 | 0xFD => Some(JPGn(13)), 132 | 0xFE => Some(COM), 133 | 0xFF => None, // Fill byte 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/upsampler.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use alloc::vec; 3 | use alloc::vec::Vec; 4 | use crate::error::{Error, Result, UnsupportedFeature}; 5 | use crate::parser::Component; 6 | 7 | pub struct Upsampler { 8 | components: Vec, 9 | line_buffer_size: usize 10 | } 11 | 12 | struct UpsamplerComponent { 13 | upsampler: Box, 14 | width: usize, 15 | height: usize, 16 | row_stride: usize, 17 | } 18 | 19 | impl Upsampler { 20 | pub fn new(components: &[Component], output_width: u16, output_height: u16) -> Result { 21 | let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap(); 22 | let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap(); 23 | let mut upsampler_components = Vec::with_capacity(components.len()); 24 | 25 | for component in components { 26 | let upsampler = choose_upsampler((component.horizontal_sampling_factor, 27 | component.vertical_sampling_factor), 28 | (h_max, v_max), 29 | output_width, 30 | output_height)?; 31 | upsampler_components.push(UpsamplerComponent { 32 | upsampler, 33 | width: component.size.width as usize, 34 | height: component.size.height as usize, 35 | row_stride: component.block_size.width as usize * component.dct_scale, 36 | }); 37 | } 38 | 39 | let buffer_size = components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize; 40 | 41 | Ok(Upsampler { 42 | components: upsampler_components, 43 | line_buffer_size: buffer_size 44 | }) 45 | } 46 | 47 | pub fn upsample_and_interleave_row(&self, component_data: &[Vec], row: usize, output_width: usize, output: &mut [u8], color_convert: fn(&[Vec], &mut [u8])) { 48 | let component_count = component_data.len(); 49 | let mut line_buffers = vec![vec![0u8; self.line_buffer_size]; component_count]; 50 | 51 | debug_assert_eq!(component_count, self.components.len()); 52 | 53 | for (i, component) in self.components.iter().enumerate() { 54 | component.upsampler.upsample_row(&component_data[i], 55 | component.width, 56 | component.height, 57 | component.row_stride, 58 | row, 59 | output_width, 60 | &mut line_buffers[i]); 61 | } 62 | color_convert(&line_buffers, output); 63 | } 64 | } 65 | 66 | struct UpsamplerH1V1; 67 | struct UpsamplerH2V1; 68 | struct UpsamplerH1V2; 69 | struct UpsamplerH2V2; 70 | 71 | struct UpsamplerGeneric { 72 | horizontal_scaling_factor: u8, 73 | vertical_scaling_factor: u8 74 | } 75 | 76 | fn choose_upsampler(sampling_factors: (u8, u8), 77 | max_sampling_factors: (u8, u8), 78 | output_width: u16, 79 | output_height: u16) -> Result> { 80 | let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1; 81 | let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1; 82 | let h2 = sampling_factors.0 * 2 == max_sampling_factors.0; 83 | let v2 = sampling_factors.1 * 2 == max_sampling_factors.1; 84 | 85 | if h1 && v1 { 86 | Ok(Box::new(UpsamplerH1V1)) 87 | } else if h2 && v1 { 88 | Ok(Box::new(UpsamplerH2V1)) 89 | } else if h1 && v2 { 90 | Ok(Box::new(UpsamplerH1V2)) 91 | } else if h2 && v2 { 92 | Ok(Box::new(UpsamplerH2V2)) 93 | } else if max_sampling_factors.0 % sampling_factors.0 != 0 94 | || max_sampling_factors.1 % sampling_factors.1 != 0 95 | { 96 | Err(Error::Unsupported( 97 | UnsupportedFeature::NonIntegerSubsamplingRatio, 98 | )) 99 | } else { 100 | Ok(Box::new(UpsamplerGeneric { 101 | horizontal_scaling_factor: max_sampling_factors.0 / sampling_factors.0, 102 | vertical_scaling_factor: max_sampling_factors.1 / sampling_factors.1, 103 | })) 104 | } 105 | } 106 | 107 | #[allow(clippy::too_many_arguments)] 108 | trait Upsample { 109 | fn upsample_row(&self, 110 | input: &[u8], 111 | input_width: usize, 112 | input_height: usize, 113 | row_stride: usize, 114 | row: usize, 115 | output_width: usize, 116 | output: &mut [u8]); 117 | } 118 | 119 | impl Upsample for UpsamplerH1V1 { 120 | fn upsample_row(&self, 121 | input: &[u8], 122 | _input_width: usize, 123 | _input_height: usize, 124 | row_stride: usize, 125 | row: usize, 126 | output_width: usize, 127 | output: &mut [u8]) { 128 | let input = &input[row * row_stride ..]; 129 | 130 | output[..output_width].copy_from_slice(&input[..output_width]); 131 | } 132 | } 133 | 134 | impl Upsample for UpsamplerH2V1 { 135 | fn upsample_row(&self, 136 | input: &[u8], 137 | input_width: usize, 138 | _input_height: usize, 139 | row_stride: usize, 140 | row: usize, 141 | _output_width: usize, 142 | output: &mut [u8]) { 143 | let input = &input[row * row_stride ..]; 144 | 145 | if input_width == 1 { 146 | output[0] = input[0]; 147 | output[1] = input[0]; 148 | return; 149 | } 150 | 151 | output[0] = input[0]; 152 | output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8; 153 | 154 | for i in 1 .. input_width - 1 { 155 | let sample = 3 * input[i] as u32 + 2; 156 | output[i * 2] = ((sample + input[i - 1] as u32) >> 2) as u8; 157 | output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8; 158 | } 159 | 160 | output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8; 161 | output[(input_width - 1) * 2 + 1] = input[input_width - 1]; 162 | } 163 | } 164 | 165 | impl Upsample for UpsamplerH1V2 { 166 | fn upsample_row(&self, 167 | input: &[u8], 168 | _input_width: usize, 169 | input_height: usize, 170 | row_stride: usize, 171 | row: usize, 172 | output_width: usize, 173 | output: &mut [u8]) { 174 | let row_near = row as f32 / 2.0; 175 | // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we 176 | // want it to be the next row. 177 | let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); 178 | 179 | let input_near = &input[row_near as usize * row_stride ..]; 180 | let input_far = &input[row_far as usize * row_stride ..]; 181 | 182 | let output = &mut output[..output_width]; 183 | let input_near = &input_near[..output_width]; 184 | let input_far = &input_far[..output_width]; 185 | for i in 0..output_width { 186 | output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8; 187 | } 188 | } 189 | } 190 | 191 | impl Upsample for UpsamplerH2V2 { 192 | fn upsample_row(&self, 193 | input: &[u8], 194 | input_width: usize, 195 | input_height: usize, 196 | row_stride: usize, 197 | row: usize, 198 | _output_width: usize, 199 | output: &mut [u8]) { 200 | let row_near = row as f32 / 2.0; 201 | // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we 202 | // want it to be the next row. 203 | let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); 204 | 205 | let input_near = &input[row_near as usize * row_stride ..]; 206 | let input_far = &input[row_far as usize * row_stride ..]; 207 | 208 | if input_width == 1 { 209 | let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8; 210 | output[0] = value; 211 | output[1] = value; 212 | return; 213 | } 214 | 215 | let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32; 216 | output[0] = ((t1 + 2) >> 2) as u8; 217 | 218 | for i in 1 .. input_width { 219 | let t0 = t1; 220 | t1 = 3 * input_near[i] as u32 + input_far[i] as u32; 221 | 222 | output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8; 223 | output[i * 2] = ((3 * t1 + t0 + 8) >> 4) as u8; 224 | } 225 | 226 | output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8; 227 | } 228 | } 229 | 230 | impl Upsample for UpsamplerGeneric { 231 | // Uses nearest neighbor sampling 232 | fn upsample_row(&self, 233 | input: &[u8], 234 | input_width: usize, 235 | _input_height: usize, 236 | row_stride: usize, 237 | row: usize, 238 | _output_width: usize, 239 | output: &mut [u8]) { 240 | let mut index = 0; 241 | let start = (row / self.vertical_scaling_factor as usize) * row_stride; 242 | let input = &input[start..(start + input_width)]; 243 | for val in input { 244 | for _ in 0..self.horizontal_scaling_factor { 245 | output[index] = *val; 246 | index += 1; 247 | } 248 | } 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /src/worker/immediate.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec; 2 | use alloc::vec::Vec; 3 | use core::mem; 4 | use crate::decoder::MAX_COMPONENTS; 5 | use crate::error::Result; 6 | use crate::idct::dequantize_and_idct_block; 7 | use crate::alloc::sync::Arc; 8 | use crate::parser::Component; 9 | use super::{RowData, Worker}; 10 | 11 | pub struct ImmediateWorker { 12 | offsets: [usize; MAX_COMPONENTS], 13 | results: Vec>, 14 | components: Vec>, 15 | quantization_tables: Vec>>, 16 | } 17 | 18 | impl Default for ImmediateWorker { 19 | fn default() -> Self { 20 | ImmediateWorker { 21 | offsets: [0; MAX_COMPONENTS], 22 | results: vec![Vec::new(); MAX_COMPONENTS], 23 | components: vec![None; MAX_COMPONENTS], 24 | quantization_tables: vec![None; MAX_COMPONENTS], 25 | } 26 | } 27 | } 28 | 29 | impl ImmediateWorker { 30 | pub fn start_immediate(&mut self, data: RowData) { 31 | assert!(self.results[data.index].is_empty()); 32 | 33 | self.offsets[data.index] = 0; 34 | self.results[data.index].resize(data.component.block_size.width as usize * data.component.block_size.height as usize * data.component.dct_scale * data.component.dct_scale, 0u8); 35 | self.components[data.index] = Some(data.component); 36 | self.quantization_tables[data.index] = Some(data.quantization_table); 37 | } 38 | 39 | pub fn append_row_immediate(&mut self, (index, data): (usize, Vec)) { 40 | // Convert coefficients from a MCU row to samples. 41 | 42 | let component = self.components[index].as_ref().unwrap(); 43 | let quantization_table = self.quantization_tables[index].as_ref().unwrap(); 44 | let block_count = component.block_size.width as usize * component.vertical_sampling_factor as usize; 45 | let line_stride = component.block_size.width as usize * component.dct_scale; 46 | 47 | assert_eq!(data.len(), block_count * 64); 48 | 49 | for i in 0..block_count { 50 | let x = (i % component.block_size.width as usize) * component.dct_scale; 51 | let y = (i / component.block_size.width as usize) * component.dct_scale; 52 | 53 | let coefficients = data[i * 64..(i + 1) * 64].try_into().unwrap(); 54 | let output = &mut self.results[index][self.offsets[index] + y * line_stride + x..]; 55 | 56 | dequantize_and_idct_block(component.dct_scale, coefficients, quantization_table, line_stride, output); 57 | } 58 | 59 | self.offsets[index] += block_count * component.dct_scale * component.dct_scale; 60 | } 61 | 62 | pub fn get_result_immediate(&mut self, index: usize) -> Vec { 63 | mem::take(&mut self.results[index]) 64 | } 65 | } 66 | 67 | impl Worker for ImmediateWorker { 68 | fn start(&mut self, data: RowData) -> Result<()> { 69 | self.start_immediate(data); 70 | Ok(()) 71 | } 72 | fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { 73 | self.append_row_immediate(row); 74 | Ok(()) 75 | } 76 | fn get_result(&mut self, index: usize) -> Result> { 77 | Ok(self.get_result_immediate(index)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/worker/mod.rs: -------------------------------------------------------------------------------- 1 | mod immediate; 2 | mod multithreaded; 3 | #[cfg(all( 4 | not(any(target_arch = "asmjs", target_arch = "wasm32")), 5 | feature = "rayon" 6 | ))] 7 | mod rayon; 8 | 9 | use crate::decoder::{choose_color_convert_func, ColorTransform}; 10 | use crate::error::Result; 11 | use crate::parser::{Component, Dimensions}; 12 | use crate::upsampler::Upsampler; 13 | 14 | use alloc::sync::Arc; 15 | use alloc::vec::Vec; 16 | use core::cell::RefCell; 17 | 18 | pub struct RowData { 19 | pub index: usize, 20 | pub component: Component, 21 | pub quantization_table: Arc<[u16; 64]>, 22 | } 23 | 24 | pub trait Worker { 25 | fn start(&mut self, row_data: RowData) -> Result<()>; 26 | fn append_row(&mut self, row: (usize, Vec)) -> Result<()>; 27 | fn get_result(&mut self, index: usize) -> Result>; 28 | /// Default implementation for spawning multiple tasks. 29 | fn append_rows(&mut self, row: &mut dyn Iterator)>) -> Result<()> { 30 | for item in row { 31 | self.append_row(item)?; 32 | } 33 | Ok(()) 34 | } 35 | } 36 | 37 | #[allow(dead_code)] 38 | pub enum PreferWorkerKind { 39 | Immediate, 40 | Multithreaded, 41 | } 42 | 43 | #[derive(Default)] 44 | pub struct WorkerScope { 45 | inner: core::cell::RefCell>, 46 | } 47 | 48 | enum WorkerScopeInner { 49 | #[cfg(all( 50 | not(any(target_arch = "asmjs", target_arch = "wasm32")), 51 | feature = "rayon" 52 | ))] 53 | Rayon(Box), 54 | #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] 55 | Multithreaded(multithreaded::MpscWorker), 56 | Immediate(immediate::ImmediateWorker), 57 | } 58 | 59 | impl WorkerScope { 60 | pub fn with(with: impl FnOnce(&Self) -> T) -> T { 61 | with(&WorkerScope { 62 | inner: RefCell::default(), 63 | }) 64 | } 65 | 66 | pub fn get_or_init_worker( 67 | &self, 68 | prefer: PreferWorkerKind, 69 | f: impl FnOnce(&mut dyn Worker) -> T, 70 | ) -> T { 71 | let mut inner = self.inner.borrow_mut(); 72 | let inner = inner.get_or_insert_with(move || match prefer { 73 | #[cfg(all( 74 | not(any(target_arch = "asmjs", target_arch = "wasm32")), 75 | feature = "rayon" 76 | ))] 77 | PreferWorkerKind::Multithreaded => WorkerScopeInner::Rayon(Default::default()), 78 | #[allow(unreachable_patterns)] 79 | #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] 80 | PreferWorkerKind::Multithreaded => WorkerScopeInner::Multithreaded(Default::default()), 81 | _ => WorkerScopeInner::Immediate(Default::default()), 82 | }); 83 | 84 | f(match &mut *inner { 85 | #[cfg(all( 86 | not(any(target_arch = "asmjs", target_arch = "wasm32")), 87 | feature = "rayon" 88 | ))] 89 | WorkerScopeInner::Rayon(worker) => worker.as_mut(), 90 | #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] 91 | WorkerScopeInner::Multithreaded(worker) => worker, 92 | WorkerScopeInner::Immediate(worker) => worker, 93 | }) 94 | } 95 | } 96 | 97 | pub fn compute_image_parallel( 98 | components: &[Component], 99 | data: Vec>, 100 | output_size: Dimensions, 101 | color_transform: ColorTransform, 102 | ) -> Result> { 103 | #[cfg(all( 104 | not(any(target_arch = "asmjs", target_arch = "wasm32")), 105 | feature = "rayon" 106 | ))] 107 | return rayon::compute_image_parallel(components, data, output_size, color_transform); 108 | 109 | #[allow(unreachable_code)] 110 | { 111 | let color_convert_func = choose_color_convert_func(components.len(), color_transform)?; 112 | let upsampler = Upsampler::new(components, output_size.width, output_size.height)?; 113 | let line_size = output_size.width as usize * components.len(); 114 | let mut image = vec![0u8; line_size * output_size.height as usize]; 115 | 116 | for (row, line) in image.chunks_mut(line_size).enumerate() { 117 | upsampler.upsample_and_interleave_row( 118 | &data, 119 | row, 120 | output_size.width as usize, 121 | line, 122 | color_convert_func, 123 | ); 124 | } 125 | 126 | Ok(image) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/worker/multithreaded.rs: -------------------------------------------------------------------------------- 1 | //! This module implements per-component parallelism. 2 | //! It should be possible to implement per-row parallelism as well, 3 | //! which should also boost performance of grayscale images 4 | //! and allow scaling to more cores. 5 | //! However, that would be more complex, so we use this as a starting point. 6 | 7 | use super::immediate::ImmediateWorker; 8 | use super::{RowData, Worker}; 9 | use crate::decoder::MAX_COMPONENTS; 10 | use crate::error::Result; 11 | use std::{ 12 | mem, 13 | sync::mpsc::{self, Receiver, Sender}, 14 | }; 15 | 16 | enum WorkerMsg { 17 | Start(RowData), 18 | AppendRow(Vec), 19 | GetResult(Sender>), 20 | } 21 | 22 | #[derive(Default)] 23 | pub struct MpscWorker { 24 | senders: [Option>; MAX_COMPONENTS], 25 | } 26 | 27 | impl MpscWorker { 28 | fn start_with( 29 | &mut self, 30 | row_data: RowData, 31 | spawn_worker: impl FnOnce(usize) -> Result>, 32 | ) -> Result<()> { 33 | // if there is no worker thread for this component yet, start one 34 | let component = row_data.index; 35 | if self.senders[component].is_none() { 36 | let sender = spawn_worker(component)?; 37 | self.senders[component] = Some(sender); 38 | } 39 | 40 | // we do the "take out value and put it back in once we're done" dance here 41 | // and in all other message-passing methods because there's not that many rows 42 | // and this should be cheaper than spawning MAX_COMPONENTS many threads up front 43 | let sender = self.senders[component].as_mut().unwrap(); 44 | sender 45 | .send(WorkerMsg::Start(row_data)) 46 | .expect("jpeg-decoder worker thread error"); 47 | Ok(()) 48 | } 49 | 50 | fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { 51 | let component = row.0; 52 | let sender = self.senders[component].as_mut().unwrap(); 53 | sender 54 | .send(WorkerMsg::AppendRow(row.1)) 55 | .expect("jpeg-decoder worker thread error"); 56 | Ok(()) 57 | } 58 | 59 | fn get_result_with( 60 | &mut self, 61 | index: usize, 62 | collect: impl FnOnce(Receiver>) -> Vec, 63 | ) -> Result> { 64 | let (tx, rx) = mpsc::channel(); 65 | let sender = mem::take(&mut self.senders[index]).unwrap(); 66 | sender 67 | .send(WorkerMsg::GetResult(tx)) 68 | .expect("jpeg-decoder worker thread error"); 69 | Ok(collect(rx)) 70 | } 71 | } 72 | 73 | impl Worker for MpscWorker { 74 | fn start(&mut self, row_data: RowData) -> Result<()> { 75 | self.start_with(row_data, spawn_worker_thread) 76 | } 77 | fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { 78 | MpscWorker::append_row(self, row) 79 | } 80 | fn get_result(&mut self, index: usize) -> Result> { 81 | self.get_result_with(index, collect_worker_thread) 82 | } 83 | } 84 | 85 | fn create_worker() -> (Sender, impl FnOnce() + 'static) { 86 | let (tx, rx) = mpsc::channel(); 87 | let closure = move || { 88 | let mut worker = ImmediateWorker::default(); 89 | 90 | while let Ok(message) = rx.recv() { 91 | match message { 92 | WorkerMsg::Start(mut data) => { 93 | // we always set component index to 0 for worker threads 94 | // because they only ever handle one per thread and we don't want them 95 | // to attempt to access nonexistent components 96 | data.index = 0; 97 | worker.start_immediate(data); 98 | } 99 | WorkerMsg::AppendRow(row) => { 100 | worker.append_row_immediate((0, row)); 101 | } 102 | WorkerMsg::GetResult(chan) => { 103 | let _ = chan.send(worker.get_result_immediate(0)); 104 | break; 105 | } 106 | } 107 | } 108 | }; 109 | 110 | (tx, closure) 111 | } 112 | 113 | fn spawn_worker_thread(component: usize) -> Result> { 114 | let (tx, worker) = create_worker(); 115 | let thread_builder = 116 | std::thread::Builder::new().name(format!("worker thread for component {}", component)); 117 | thread_builder.spawn(worker)?; 118 | Ok(tx) 119 | } 120 | 121 | fn collect_worker_thread(rx: Receiver>) -> Vec { 122 | rx.recv().expect("jpeg-decoder worker thread error") 123 | } 124 | -------------------------------------------------------------------------------- /src/worker/rayon.rs: -------------------------------------------------------------------------------- 1 | use rayon::iter::{IndexedParallelIterator, ParallelIterator}; 2 | use rayon::slice::ParallelSliceMut; 3 | 4 | use crate::decoder::{choose_color_convert_func, ColorTransform}; 5 | use crate::error::Result; 6 | use crate::idct::dequantize_and_idct_block; 7 | use crate::parser::Component; 8 | use crate::upsampler::Upsampler; 9 | use crate::{decoder::MAX_COMPONENTS, parser::Dimensions}; 10 | 11 | use std::sync::Arc; 12 | 13 | use super::{RowData, Worker}; 14 | 15 | /// Technically similar to `immediate::ImmediateWorker` but we copy it since we may prefer 16 | /// different style of managing the memory allocation, something that multiple actors can access in 17 | /// parallel. 18 | #[derive(Default)] 19 | struct ImmediateWorker { 20 | offsets: [usize; MAX_COMPONENTS], 21 | results: [Vec; MAX_COMPONENTS], 22 | components: [Option; MAX_COMPONENTS], 23 | quantization_tables: [Option>; MAX_COMPONENTS], 24 | } 25 | 26 | #[derive(Clone, Copy)] 27 | struct ComponentMetadata { 28 | block_width: usize, 29 | block_count: usize, 30 | line_stride: usize, 31 | dct_scale: usize, 32 | } 33 | 34 | #[derive(Default)] 35 | pub struct Scoped { 36 | inner: ImmediateWorker, 37 | } 38 | 39 | impl ImmediateWorker { 40 | pub fn start_immediate(&mut self, data: RowData) { 41 | let elements = data.component.block_size.width as usize 42 | * data.component.block_size.height as usize 43 | * data.component.dct_scale 44 | * data.component.dct_scale; 45 | self.offsets[data.index] = 0; 46 | self.results[data.index].resize(elements, 0u8); 47 | self.components[data.index] = Some(data.component); 48 | self.quantization_tables[data.index] = Some(data.quantization_table); 49 | } 50 | 51 | pub fn get_result_immediate(&mut self, index: usize) -> Vec { 52 | core::mem::take(&mut self.results[index]) 53 | } 54 | 55 | pub fn component_metadata(&self, index: usize) -> Option { 56 | let component = self.components[index].as_ref()?; 57 | let block_size = component.block_size; 58 | let block_width = block_size.width as usize; 59 | let block_count = block_size.width as usize * component.vertical_sampling_factor as usize; 60 | let line_stride = block_size.width as usize * component.dct_scale; 61 | let dct_scale = component.dct_scale; 62 | 63 | Some(ComponentMetadata { 64 | block_width, 65 | block_count, 66 | line_stride, 67 | dct_scale, 68 | }) 69 | } 70 | 71 | pub fn append_row_locked( 72 | quantization_table: Arc<[u16; 64]>, 73 | metadata: ComponentMetadata, 74 | data: Vec, 75 | result_block: &mut [u8], 76 | ) { 77 | // Convert coefficients from a MCU row to samples. 78 | let ComponentMetadata { 79 | block_count, 80 | line_stride, 81 | block_width, 82 | dct_scale, 83 | } = metadata; 84 | 85 | assert_eq!(data.len(), block_count * 64); 86 | 87 | let mut output_buffer = [0; 64]; 88 | for i in 0..block_count { 89 | let x = (i % block_width) * dct_scale; 90 | let y = (i / block_width) * dct_scale; 91 | 92 | let coefficients: &[i16; 64] = &data[i * 64..(i + 1) * 64].try_into().unwrap(); 93 | 94 | // Write to a temporary intermediate buffer, a 8x8 'image'. 95 | dequantize_and_idct_block( 96 | dct_scale, 97 | coefficients, 98 | &quantization_table, 99 | 8, 100 | &mut output_buffer, 101 | ); 102 | 103 | let write_back = &mut result_block[y * line_stride + x..]; 104 | 105 | let buffered_lines = output_buffer.chunks_mut(8); 106 | let back_lines = write_back.chunks_mut(line_stride); 107 | 108 | for (buf, back) in buffered_lines.zip(back_lines).take(dct_scale) { 109 | back[..dct_scale].copy_from_slice(&buf[..dct_scale]); 110 | } 111 | } 112 | } 113 | } 114 | 115 | impl Worker for Scoped { 116 | fn start(&mut self, row_data: RowData) -> Result<()> { 117 | self.inner.start_immediate(row_data); 118 | Ok(()) 119 | } 120 | 121 | fn append_row(&mut self, row: (usize, Vec)) -> Result<()> { 122 | let inner = &mut self.inner; 123 | let (index, data) = row; 124 | 125 | let quantization_table = inner.quantization_tables[index].as_ref().unwrap().clone(); 126 | let metadata = inner.component_metadata(index).unwrap(); 127 | let result_block = &mut inner.results[index][inner.offsets[index]..]; 128 | inner.offsets[index] += metadata.bytes_used(); 129 | 130 | ImmediateWorker::append_row_locked(quantization_table, metadata, data, result_block); 131 | Ok(()) 132 | } 133 | 134 | fn get_result(&mut self, index: usize) -> Result> { 135 | let result = self.inner.get_result_immediate(index); 136 | Ok(result) 137 | } 138 | 139 | // Magic sauce, these _may_ run in parallel. 140 | fn append_rows(&mut self, iter: &mut dyn Iterator)>) -> Result<()> { 141 | let inner = &mut self.inner; 142 | rayon::in_place_scope(|scope| { 143 | let metadatas = [ 144 | inner.component_metadata(0), 145 | inner.component_metadata(1), 146 | inner.component_metadata(2), 147 | inner.component_metadata(3), 148 | ]; 149 | 150 | let [res0, res1, res2, res3] = &mut inner.results; 151 | 152 | // Lazily get the blocks. Note: if we've already collected results from a component 153 | // then the result vector has already been deallocated/taken. But no more tasks should 154 | // be created for it. 155 | let mut result_blocks = [ 156 | res0.get_mut(inner.offsets[0]..).unwrap_or(&mut []), 157 | res1.get_mut(inner.offsets[1]..).unwrap_or(&mut []), 158 | res2.get_mut(inner.offsets[2]..).unwrap_or(&mut []), 159 | res3.get_mut(inner.offsets[3]..).unwrap_or(&mut []), 160 | ]; 161 | 162 | // First we schedule everything, making sure their index is right etc. 163 | for (index, data) in iter { 164 | let metadata = metadatas[index].unwrap(); 165 | let quantization_table = inner.quantization_tables[index].as_ref().unwrap().clone(); 166 | 167 | inner.offsets[index] += metadata.bytes_used(); 168 | let (result_block, tail) = 169 | core::mem::take(&mut result_blocks[index]).split_at_mut(metadata.bytes_used()); 170 | result_blocks[index] = tail; 171 | 172 | scope.spawn(move |_| { 173 | ImmediateWorker::append_row_locked( 174 | quantization_table, 175 | metadata, 176 | data, 177 | result_block, 178 | ) 179 | }); 180 | } 181 | }); 182 | 183 | Ok(()) 184 | } 185 | } 186 | 187 | impl ComponentMetadata { 188 | fn bytes_used(&self) -> usize { 189 | self.block_count * self.dct_scale * self.dct_scale 190 | } 191 | } 192 | 193 | pub fn compute_image_parallel( 194 | components: &[Component], 195 | data: Vec>, 196 | output_size: Dimensions, 197 | color_transform: ColorTransform, 198 | ) -> Result> { 199 | let color_convert_func = choose_color_convert_func(components.len(), color_transform)?; 200 | let upsampler = Upsampler::new(components, output_size.width, output_size.height)?; 201 | let line_size = output_size.width as usize * components.len(); 202 | let mut image = vec![0u8; line_size * output_size.height as usize]; 203 | 204 | image 205 | .par_chunks_mut(line_size) 206 | .with_max_len(1) 207 | .enumerate() 208 | .for_each(|(row, line)| { 209 | upsampler.upsample_and_interleave_row( 210 | &data, 211 | row, 212 | output_size.width as usize, 213 | line, 214 | color_convert_func, 215 | ); 216 | }); 217 | 218 | Ok(image) 219 | } 220 | -------------------------------------------------------------------------------- /tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{BufRead, BufReader}; 3 | use std::path::{Path, PathBuf}; 4 | use walkdir::WalkDir; 5 | 6 | pub fn test_files(test_dir: &Path) -> Vec { 7 | let mut test_files = vec![]; 8 | 9 | for entry in WalkDir::new(&test_dir) { 10 | let entry = entry.unwrap(); 11 | let path = entry.path(); 12 | 13 | if let Some(extension) = path.extension() { 14 | if path.is_file() && (extension == "jpg" || extension == "jpeg") { 15 | test_files.push(path.to_owned()); 16 | } 17 | } 18 | } 19 | 20 | if let Ok(file) = File::open(test_dir.join("disabled.list")) { 21 | for line in BufReader::new(file).lines() { 22 | let line = line.unwrap(); 23 | 24 | if line.is_empty() || line.starts_with("#") { 25 | continue; 26 | } 27 | 28 | let path = test_dir.join(Path::new(&line)); 29 | 30 | if !test_files.contains(&path) { 31 | panic!("The file {line:?} specified in {:?} could not be found among the files being tested", test_dir.join("disabled.txt")); 32 | } 33 | 34 | let position = test_files.iter().position(|p| p == &path).unwrap(); 35 | test_files.remove(position); 36 | } 37 | } 38 | 39 | test_files 40 | } 41 | -------------------------------------------------------------------------------- /tests/crashtest/images/README.md: -------------------------------------------------------------------------------- 1 | # File sources 2 | File | Source 3 | --------------------------| ------ 4 | imagetestsuite/ | The files in this directory were taken from https://code.google.com/p/imagetestsuite/ 5 | dc-predictor-overflow.jpg | Found by Wim Looman (@Nemo157) while fuzzing 6 | derive-huffman-codes-overflow.jpg | Found by Pascal Hertleif (@killercup) while fuzzing 7 | missing-sof.jpg | Found by Corey Farwell (@frewsxcv) when fuzz testing 8 | extraneous-bytes-after-sos.jpg | Scan from brother DSmobile 920DW provided by Filip Lundborg (@filipl) 9 | missing-sos.jpg | Generated in GIMP and manually edited by John Reynolds (@quilan1) 10 | missing-frame-image-1410.jpg | Found by @frewsxcv when fuzzing 11 | -------------------------------------------------------------------------------- /tests/crashtest/images/dc-predictor-overflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/dc-predictor-overflow.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/derive-huffman-codes-overflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/derive-huffman-codes-overflow.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/empty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/empty.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/extraneous-bytes-after-sos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/extraneous-bytes-after-sos.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/138d3b9e0d9fbf641b8135981e597c3a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/138d3b9e0d9fbf641b8135981e597c3a.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/194531363df5b73f59c4c0517422f917.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/194531363df5b73f59c4c0517422f917.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/1cbb1bb37d62c44f67374cd451643dc4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/1cbb1bb37d62c44f67374cd451643dc4.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/2183d39878e734cf79b62428b02fafb5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/2183d39878e734cf79b62428b02fafb5.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/21a84b8472f6d18f5bb5c0026e97cfaa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/21a84b8472f6d18f5bb5c0026e97cfaa.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/21ad703b38e2c350215bb92a849486f3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/21ad703b38e2c350215bb92a849486f3.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/255015e07b6f9137b53b0f97d67a8aef.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/255015e07b6f9137b53b0f97d67a8aef.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/28968137f4fc75fbf56f16d7a7a8551a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/28968137f4fc75fbf56f16d7a7a8551a.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/28c74d9284d9836017fd519f6932efd8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/28c74d9284d9836017fd519f6932efd8.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/2c9e7a1805f8b47630bbb83d21bf8222.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/2c9e7a1805f8b47630bbb83d21bf8222.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/316be81dfdeeb942e904feb3a77f4f83.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/316be81dfdeeb942e904feb3a77f4f83.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/32d08f4a5eb10332506ebedbb9bc7257.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/32d08f4a5eb10332506ebedbb9bc7257.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/3976a754ef0aca80e84e2c403d714579.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/3976a754ef0aca80e84e2c403d714579.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/39f43f280b31152f1d27df3f9d189317.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/39f43f280b31152f1d27df3f9d189317.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/3ba6af611cc5467cfdbd5566561b8478.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/3ba6af611cc5467cfdbd5566561b8478.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/3cc4a7fc6481ea3681138da4643f3d16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/3cc4a7fc6481ea3681138da4643f3d16.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/3ea649db8e81a46ca4f92fb3238f78ff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/3ea649db8e81a46ca4f92fb3238f78ff.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/3ef05501315073d9d4e1c6b654d99ac0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/3ef05501315073d9d4e1c6b654d99ac0.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/4085c929e00c446d3fee18b5b20a27f9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/4085c929e00c446d3fee18b5b20a27f9.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/40bb78b1ac031125a6d8466b374962a8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/40bb78b1ac031125a6d8466b374962a8.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/46e5ac4a62d7a445a7c1fb704fafe05c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/46e5ac4a62d7a445a7c1fb704fafe05c.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/46f5d9c1b0fe352353688f736e5617b6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/46f5d9c1b0fe352353688f736e5617b6.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/4838ece0d3900220d33528ee027289bc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/4838ece0d3900220d33528ee027289bc.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5315c35bbcc28d8eee419028ac9f38e0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5315c35bbcc28d8eee419028ac9f38e0.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5482a54657765056f1a94116a8dbffe7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5482a54657765056f1a94116a8dbffe7.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/551c2656a4f6f9f5ea7e9945b9081202.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/551c2656a4f6f9f5ea7e9945b9081202.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5633ed9d0eb700d0093bf85d86a95ebf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5633ed9d0eb700d0093bf85d86a95ebf.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/56d4a1bb53241f7c5ed6ab531320a542.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/56d4a1bb53241f7c5ed6ab531320a542.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/59d3b529c78ac722127c41ba75b3355b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/59d3b529c78ac722127c41ba75b3355b.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5a43fa2cf9c1e47f0331ef71b928ee55.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5a43fa2cf9c1e47f0331ef71b928ee55.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5baad44ca4702949724234e35c5bb341.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5baad44ca4702949724234e35c5bb341.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5bc61724b33e34a6188a817f9f2f8138.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5bc61724b33e34a6188a817f9f2f8138.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5c67195f6993c9f8d0d32d4ffe0d8e62.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5c67195f6993c9f8d0d32d4ffe0d8e62.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/5dc71b1d868ef137394d3cc23abea65a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/5dc71b1d868ef137394d3cc23abea65a.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/627c0779eb46b98f751187c5c9f43aa3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/627c0779eb46b98f751187c5c9f43aa3.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/6903d4538fd33c8fd0ded32cb30d618e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/6903d4538fd33c8fd0ded32cb30d618e.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/6de166ee2a3a60df9017650e2a808408.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/6de166ee2a3a60df9017650e2a808408.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/72d091e08c93c9e590360130fa35221b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/72d091e08c93c9e590360130fa35221b.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/754664a12e36abff7950e796c906ae39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/754664a12e36abff7950e796c906ae39.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/75e4bd7544a85af6438497980b62fba5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/75e4bd7544a85af6438497980b62fba5.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/786b67badc535fc95a4a76c29a0e0146.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/786b67badc535fc95a4a76c29a0e0146.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/7997b6b229f25315d33f5c7085e37500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/7997b6b229f25315d33f5c7085e37500.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/79f5fc6bca756e1f067c6fc83e18b32e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/79f5fc6bca756e1f067c6fc83e18b32e.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/7acc832f70b2ca62e58a953f3b90fd82.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/7acc832f70b2ca62e58a953f3b90fd82.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/7dbf474f80e466e9e25ee46b84166420.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/7dbf474f80e466e9e25ee46b84166420.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/7e7cdf7f4ee50b308531313bbf43e0c3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/7e7cdf7f4ee50b308531313bbf43e0c3.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/8417a305e3b43d5b1bda4ff06a660c54.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/8417a305e3b43d5b1bda4ff06a660c54.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/8546907dbe574744d7fea6ca9de1de6b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/8546907dbe574744d7fea6ca9de1de6b.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/865db3dd2d380626f16b6f9dc6d62dba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/865db3dd2d380626f16b6f9dc6d62dba.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/897b8b6d8feb466aa6cad5f512c3fce2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/897b8b6d8feb466aa6cad5f512c3fce2.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/8a9cc8eeed66aeb423a91c44111d9450.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/8a9cc8eeed66aeb423a91c44111d9450.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/8e330afbd99ba01b66570ed62fcdc6ab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/8e330afbd99ba01b66570ed62fcdc6ab.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/8e5e74dbf9b68a322fbb9512db837329.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/8e5e74dbf9b68a322fbb9512db837329.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/90e46387f562ca8fa106b51dfcda1dc6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/90e46387f562ca8fa106b51dfcda1dc6.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/96b3e939852157613fa2e48d58fe35fe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/96b3e939852157613fa2e48d58fe35fe.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/9efd60f04cd971daa83d3131e6d6f389.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/9efd60f04cd971daa83d3131e6d6f389.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/a17806f32b45d63eea5230e7893e1f15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/a17806f32b45d63eea5230e7893e1f15.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/a54f8c866cbef6e6cda858c85d72dfc8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/a54f8c866cbef6e6cda858c85d72dfc8.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/a7326ba8f3f4559991126474dd30083d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/a7326ba8f3f4559991126474dd30083d.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/acb1fac4e618f636d415f62496e8b70e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/acb1fac4e618f636d415f62496e8b70e.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/acce3629083f0e348e94fb58f952d3de.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/acce3629083f0e348e94fb58f952d3de.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/adcb34b94f4c839bdd29037419a0ee53.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/adcb34b94f4c839bdd29037419a0ee53.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/b0b8914cc5f7a6eff409f16d8cc236c5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/b0b8914cc5f7a6eff409f16d8cc236c5.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/b4103df93880fc5677c2a081e4bfc712.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/b4103df93880fc5677c2a081e4bfc712.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/b5369bcbddca7135a5708c5237ad64e4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/b5369bcbddca7135a5708c5237ad64e4.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/b55977028a3a574336966b6536640fc9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/b55977028a3a574336966b6536640fc9.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/ba60305ac83fe3d8ef01da1d9a0ecc79.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/ba60305ac83fe3d8ef01da1d9a0ecc79.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/bd8cf05698aee36b82b4caf58edea442.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/bd8cf05698aee36b82b4caf58edea442.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c1ca5583e4bfadc73e7fe9418b6e6bf4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c1ca5583e4bfadc73e7fe9418b6e6bf4.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c3018ebe53d0046eecb58858ca869a99.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c3018ebe53d0046eecb58858ca869a99.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c4ced510f44a9bfe85c696c05a7f791d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c4ced510f44a9bfe85c696c05a7f791d.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c52ffdd6a0346c4d09271f8ccbdfd5a3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c52ffdd6a0346c4d09271f8ccbdfd5a3.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c8bc97335529d069a753c67475b8c82c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c8bc97335529d069a753c67475b8c82c.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/c8c1a5675f82021d92b928a10c597bad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/c8c1a5675f82021d92b928a10c597bad.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/cc23dd79637b606cf5ba234a037e17ba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/cc23dd79637b606cf5ba234a037e17ba.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/cc4ee796d16c9fe68978166c7cd1ae1b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/cc4ee796d16c9fe68978166c7cd1ae1b.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/ce380515a534e8226209daae00e7b4e8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/ce380515a534e8226209daae00e7b4e8.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/d085a42245996e5750a30ccb48791bcf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/d085a42245996e5750a30ccb48791bcf.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/d15b71b8cebe35a57cc6e996cc09218b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/d15b71b8cebe35a57cc6e996cc09218b.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/d22db5be7594c17a18a047ca9264ea0a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/d22db5be7594c17a18a047ca9264ea0a.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/d3b044a94486cae0224c002800ddd642.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/d3b044a94486cae0224c002800ddd642.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/de4ae285a275bcfe2ac87c0126742552.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/de4ae285a275bcfe2ac87c0126742552.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/de5884cec093257d239f3b8be3e2f2e5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/de5884cec093257d239f3b8be3e2f2e5.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/e18bb52107598f65b81b02be2c6c5124.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/e18bb52107598f65b81b02be2c6c5124.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/e6d9eca2c7405e13cfb850b7d0ef7476.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/e6d9eca2c7405e13cfb850b7d0ef7476.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/eddea4ef9629be031f750a8ff0b7497c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/eddea4ef9629be031f750a8ff0b7497c.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/eecb78b937a7c5f04aae2f5b0f5b5acc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/eecb78b937a7c5f04aae2f5b0f5b5acc.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/ef1f8a057bb6056674fad92f6b8c0acd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/ef1f8a057bb6056674fad92f6b8c0acd.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/ef724193653930f52acffa90e6426fd2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/ef724193653930f52acffa90e6426fd2.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f006e96f3b27fdfaa075322d759ea2e8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f006e96f3b27fdfaa075322d759ea2e8.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f012a4321f00f12af6b1eee7580ffb9c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f012a4321f00f12af6b1eee7580ffb9c.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f1fad47f213bb64c99f714652f30e49e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f1fad47f213bb64c99f714652f30e49e.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f6419b06a39ff09604343848658b1a41.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f6419b06a39ff09604343848658b1a41.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f6b4389c3cf0f5997b2e5a4b905aea8d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f6b4389c3cf0f5997b2e5a4b905aea8d.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f6d3f522dcb693d9e731d5a0fb4e1393.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f6d3f522dcb693d9e731d5a0fb4e1393.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/f8e19feecd246156b5d7e79efc455e99.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/f8e19feecd246156b5d7e79efc455e99.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/fd44dc63fa7bdd12ee34fc602231ef02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/fd44dc63fa7bdd12ee34fc602231ef02.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/imagetestsuite/fddcfc778ada60229380c2493fc4c243.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/imagetestsuite/fddcfc778ada60229380c2493fc4c243.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/invalid-dimensions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/invalid-dimensions.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/invalid-prediction-shift.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/invalid-prediction-shift.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/max_size.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/max_size.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/missing-frame-image-1410.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/missing-frame-image-1410.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/missing-sof.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/missing-sof.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/missing-sos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/missing-sos.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/multiple-0xff-before-eoi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/multiple-0xff-before-eoi.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/null_height.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/null_height.jpg -------------------------------------------------------------------------------- /tests/crashtest/images/subtract-with-overflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/crashtest/images/subtract-with-overflow.jpg -------------------------------------------------------------------------------- /tests/crashtest/mod.rs: -------------------------------------------------------------------------------- 1 | use jpeg; 2 | use std::fs::File; 3 | use std::io::BufReader; 4 | use std::path::Path; 5 | 6 | use super::common; 7 | 8 | #[test] 9 | fn crashtest() { 10 | let files = common::test_files(&Path::new("tests").join("crashtest").join("images")); 11 | 12 | for path in &files { 13 | let file = File::open(path).unwrap(); 14 | let mut decoder = jpeg::Decoder::new(BufReader::new(file)); 15 | let _ = decoder.decode(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/icc/icc_chunk_count_mismatch.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/icc/icc_chunk_count_mismatch.jpeg -------------------------------------------------------------------------------- /tests/icc/icc_chunk_double_seq_no.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/icc/icc_chunk_double_seq_no.jpeg -------------------------------------------------------------------------------- /tests/icc/icc_chunk_order.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/icc/icc_chunk_order.jpeg -------------------------------------------------------------------------------- /tests/icc/icc_chunk_seq_no_0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/icc/icc_chunk_seq_no_0.jpeg -------------------------------------------------------------------------------- /tests/icc/icc_missing_chunk.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/icc/icc_missing_chunk.jpeg -------------------------------------------------------------------------------- /tests/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate jpeg_decoder as jpeg; 2 | extern crate png; 3 | extern crate walkdir; 4 | 5 | use std::path::Path; 6 | use std::fs::File; 7 | 8 | mod common; 9 | mod crashtest; 10 | mod reftest; 11 | 12 | #[test] 13 | #[cfg(all(target_family="wasm", target_os="unknown"))] 14 | #[wasm_bindgen_test::wasm_bindgen_test] 15 | fn included_file() { 16 | const FILE: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/reftest/images/mozilla/jpg-progressive.jpg")); 17 | 18 | let mut data = FILE; 19 | let mut decoder = jpeg::Decoder::new(&mut data); 20 | let ref_data = decoder.decode().unwrap(); 21 | let ref_info = decoder.info().unwrap(); 22 | 23 | let mut data = FILE; 24 | decoder = jpeg::Decoder::new(&mut data); 25 | decoder.read_info().unwrap(); 26 | let info = decoder.info().unwrap(); 27 | let data = decoder.decode().unwrap(); 28 | 29 | assert_eq!(info, decoder.info().unwrap()); 30 | assert_eq!(info, ref_info); 31 | assert_eq!(data, ref_data); 32 | } 33 | 34 | #[test] 35 | fn read_info() { 36 | let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); 37 | 38 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 39 | let ref_data = decoder.decode().unwrap(); 40 | let ref_info = decoder.info().unwrap(); 41 | 42 | decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 43 | decoder.read_info().unwrap(); 44 | let info = decoder.info().unwrap(); 45 | let data = decoder.decode().unwrap(); 46 | 47 | assert_eq!(info, decoder.info().unwrap()); 48 | assert_eq!(info, ref_info); 49 | assert_eq!(data, ref_data); 50 | } 51 | 52 | #[test] 53 | fn read_icc_profile() { 54 | let path = Path::new("tests") 55 | .join("reftest") 56 | .join("images") 57 | .join("mozilla") 58 | .join("jpg-srgb-icc.jpg"); 59 | 60 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 61 | decoder.decode().unwrap(); 62 | 63 | let profile = decoder.icc_profile().unwrap(); 64 | // "acsp" is a mandatory string in ICC profile headers. 65 | assert_eq!(&profile[36..40], b"acsp"); 66 | } 67 | 68 | // Test if chunks are concatenated in the correct order 69 | #[test] 70 | fn read_icc_profile_random_order() { 71 | let path = Path::new("tests") 72 | .join("icc") 73 | .join("icc_chunk_order.jpeg"); 74 | 75 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 76 | decoder.decode().unwrap(); 77 | 78 | let profile = decoder.icc_profile().unwrap(); 79 | 80 | assert_eq!(profile.len(), 254); 81 | 82 | for i in 1..=254 { 83 | assert_eq!(profile[i - 1], i as u8); 84 | } 85 | } 86 | 87 | // Check if ICC profiles with invalid chunk number 0 are discarded 88 | #[test] 89 | fn read_icc_profile_seq_no_0() { 90 | let path = Path::new("tests") 91 | .join("icc") 92 | .join("icc_chunk_seq_no_0.jpeg"); 93 | 94 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 95 | decoder.decode().unwrap(); 96 | 97 | let profile = decoder.icc_profile(); 98 | assert!(profile.is_none()); 99 | } 100 | 101 | // Check if ICC profiles with multiple chunks with the same number are discarded 102 | #[test] 103 | fn read_icc_profile_double_seq_no() { 104 | let path = Path::new("tests") 105 | .join("icc") 106 | .join("icc_chunk_double_seq_no.jpeg"); 107 | 108 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 109 | decoder.decode().unwrap(); 110 | 111 | let profile = decoder.icc_profile(); 112 | assert!(profile.is_none()); 113 | } 114 | 115 | // Check if ICC profiles with mismatching number of chunks and total chunk count are discarded 116 | #[test] 117 | fn read_icc_profile_chunk_count_mismatch() { 118 | let path = Path::new("tests") 119 | .join("icc") 120 | .join("icc_chunk_count_mismatch.jpeg"); 121 | 122 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 123 | decoder.decode().unwrap(); 124 | 125 | let profile = decoder.icc_profile(); 126 | assert!(profile.is_none()); 127 | } 128 | 129 | // Check if ICC profiles with missing chunk are discarded 130 | #[test] 131 | fn read_icc_profile_missing_chunk() { 132 | let path = Path::new("tests") 133 | .join("icc") 134 | .join("icc_missing_chunk.jpeg"); 135 | 136 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 137 | decoder.decode().unwrap(); 138 | 139 | let profile = decoder.icc_profile(); 140 | assert!(profile.is_none()); 141 | } 142 | 143 | #[test] 144 | fn read_exif_data() { 145 | let path = Path::new("tests") 146 | .join("reftest") 147 | .join("images") 148 | .join("ycck.jpg"); 149 | 150 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 151 | decoder.decode().unwrap(); 152 | 153 | let exif_data = decoder.exif_data().unwrap(); 154 | // exif data start as a TIFF header 155 | assert_eq!(&exif_data[0..8], b"\x49\x49\x2A\x00\x08\x00\x00\x00"); 156 | } 157 | 158 | #[test] 159 | fn read_xmp_data() { 160 | let path = Path::new("tests") 161 | .join("reftest") 162 | .join("images") 163 | .join("ycck.jpg"); 164 | 165 | let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); 166 | decoder.decode().unwrap(); 167 | 168 | let xmp_data = decoder.xmp_data().unwrap(); 169 | assert_eq!(&xmp_data[0..9], b" = (0..1024) 15 | .map(|_| { 16 | std::thread::spawn(move || { 17 | let mut decoder = Decoder::new(File::open(&path).unwrap()); 18 | let _ = decoder.decode().unwrap(); 19 | }); 20 | }).collect(); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/rayon.rs: -------------------------------------------------------------------------------- 1 | use std::{fs::File, path::Path}; 2 | use jpeg_decoder::Decoder; 3 | 4 | #[test] 5 | fn decoding_in_limited_threadpool_does_not_deadlock() { 6 | let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); 7 | 8 | let pool = rayon::ThreadPoolBuilder::new() 9 | .num_threads(1) 10 | .build() 11 | .unwrap(); 12 | pool.install(|| { 13 | let mut decoder = Decoder::new(File::open(&path).unwrap()); 14 | let _ = decoder.decode().unwrap(); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /tests/reftest/.gitignore: -------------------------------------------------------------------------------- 1 | *-diff.png 2 | -------------------------------------------------------------------------------- /tests/reftest/images/16bit-qtables.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/16bit-qtables.jpg -------------------------------------------------------------------------------- /tests/reftest/images/16bit-qtables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/16bit-qtables.png -------------------------------------------------------------------------------- /tests/reftest/images/README.md: -------------------------------------------------------------------------------- 1 | # PNG files 2 | All .png files in this directory were generated using `convert .jpg .png` 3 | 4 | # File sources 5 | File | Source 6 | ------------------| ------ 7 | 16bit-qtables.jpg | Created using convert mozilla/jpg-size-1x1.png tga:- | cjpeg -quality 10 -outfile 16bit-qtables.jpg 8 | extraneous-data.jpg | `mozilla/jpg-size-16x16.jpg` with 6 random bytes inserted before the EOI marker 9 | mjpeg.jpg | https://bugzilla.mozilla.org/show_bug.cgi?id=963907 10 | restarts.jpg | `mozilla/jpg-size-33x33.jpg` with added restart markers. 11 | rgb.jpg | Created from `ycck.jpg` using convert ycck.jpg tga:- | cjpeg -rgb -outfile rgb.jpg 12 | ycck.jpg | https://en.wikipedia.org/wiki/File:Channel_digital_image_CMYK_color.jpg 13 | non-interleaved-mcu.jpg | Generated in GIMP by John Reynolds (@quilan1) 14 | progressive-missing-ac.jpg | Generated in GIMP and manually edited by John Reynolds (@quilan1) 15 | progressive-missing-dc.jpg | Generated in GIMP and manually edited by John Reynolds (@quilan1) 16 | -------------------------------------------------------------------------------- /tests/reftest/images/blank_800x280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/blank_800x280.jpg -------------------------------------------------------------------------------- /tests/reftest/images/blank_800x280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/blank_800x280.png -------------------------------------------------------------------------------- /tests/reftest/images/disabled.list: -------------------------------------------------------------------------------- 1 | ycck.jpg 2 | 3 | mozilla/jpg-size-3x3.jpg 4 | mozilla/jpg-size-4x4.jpg 5 | 6 | # https://bugzilla.mozilla.org/show_bug.cgi?id=797042 7 | mozilla/jpg-size-6x6.jpg 8 | -------------------------------------------------------------------------------- /tests/reftest/images/extraneous-data.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/extraneous-data.jpg -------------------------------------------------------------------------------- /tests/reftest/images/extraneous-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/extraneous-data.png -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_16x24_sampling2x2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_16x24_sampling2x2.jpg -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_16x24_sampling2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_16x24_sampling2x2.png -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_24x16_sampling2x2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_24x16_sampling2x2.jpg -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_24x16_sampling2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_24x16_sampling2x2.png -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_large.jpg -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_large.png -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_long.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_long.jpg -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_long.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_long.png -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_square.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_square.jpg -------------------------------------------------------------------------------- /tests/reftest/images/grayscale_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/grayscale_square.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 RII-UTHSCSA 2 | Copyright (c) 2021 Victor Saase 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/README.md: -------------------------------------------------------------------------------- 1 | # JPEG Lossless data set 1 2 | 3 | The files starting with jpeg_lossless were taken from . 4 | The image data bytes were extracted from the DICOM files. 5 | The reference PNG files were created with the IJG library as distributed in the GDCM toolkit . 6 | -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1-8bit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1-8bit.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1-8bit.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1-rgb.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel1.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel2.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel2.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel3.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel3.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel4.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel4.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel5.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel5.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel6.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel6.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel7.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/jpeg_lossless_sel7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/jpeg_lossless_sel7.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/lossless16bit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/lossless16bit.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/1/lossless16bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/1/lossless16bit.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/2/MR4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/2/MR4.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/2/MR4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/2/MR4.png -------------------------------------------------------------------------------- /tests/reftest/images/lossless/2/README.md: -------------------------------------------------------------------------------- 1 | # JPEG Lossless data set 2 2 | 3 | The JPEG losssless files in this data set 4 | were collected from the DICOM-WG04 compilation of public DICOM files in 5 | (revision 2004/08/26), 6 | extracting the JPEG data from the files' pixel data. 7 | 8 | The ground truth was collected from the respective reference (uncompressed) files 9 | and converted to 16-bit PNG files. 10 | 11 | ## Description 12 | 13 | - **MR4**: 512x512, 12 bit precision, non-hierarchical, selection value 1 14 | - JPEG extracted from DICOM file `JPLL/MR4_JPLL` 15 | - Ground truth converted from DICOM file `REF/MR4_UNC` 16 | - **XA1**: 1024x1024, 10 bit precision, non-hierarchical, selection value 1 17 | - JPEG extracted from DICOM file `JPLL/XA1_JPLL` 18 | - Ground truth converted from DICOM file `REF/XA1_UNC` 19 | -------------------------------------------------------------------------------- /tests/reftest/images/lossless/2/XA1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/2/XA1.jpg -------------------------------------------------------------------------------- /tests/reftest/images/lossless/2/XA1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/lossless/2/XA1.png -------------------------------------------------------------------------------- /tests/reftest/images/mjpeg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mjpeg.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mjpeg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mjpeg.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/README.md: -------------------------------------------------------------------------------- 1 | # mozilla 2 | The files in this directory were taken from https://hg.mozilla.org/mozilla-central/file/tip/image/test/reftest/jpeg 3 | 4 | The following changes were made: 5 | * `jpg-gray.png` and `jpg-srgb-icc.png` were converted from RGB to grayscale using `convert -colorspace gray ` to match the pixel format of the corresponding JPEG files. 6 | -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-cmyk-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-cmyk-1.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-cmyk-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-cmyk-1.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-cmyk-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-cmyk-2.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-cmyk-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-cmyk-2.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-gray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-gray.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-gray.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-progressive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-progressive.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-progressive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-progressive.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-15x15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-15x15.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-15x15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-15x15.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-16x16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-16x16.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-16x16.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-17x17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-17x17.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-17x17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-17x17.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-1x1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-1x1.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-1x1.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-2x2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-2x2.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-2x2.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-31x31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-31x31.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-31x31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-31x31.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-32x32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-32x32.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-32x32.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-33x33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-33x33.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-33x33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-33x33.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-3x3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-3x3.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-3x3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-3x3.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-4x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-4x4.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-4x4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-4x4.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-5x5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-5x5.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-5x5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-5x5.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-6x6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-6x6.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-6x6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-6x6.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-7x7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-7x7.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-7x7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-7x7.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-8x8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-8x8.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-8x8.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-9x9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-9x9.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-size-9x9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-size-9x9.png -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-srgb-icc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-srgb-icc.jpg -------------------------------------------------------------------------------- /tests/reftest/images/mozilla/jpg-srgb-icc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/mozilla/jpg-srgb-icc.png -------------------------------------------------------------------------------- /tests/reftest/images/non-interleaved-mcu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/non-interleaved-mcu.jpg -------------------------------------------------------------------------------- /tests/reftest/images/non-interleaved-mcu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/non-interleaved-mcu.png -------------------------------------------------------------------------------- /tests/reftest/images/partial_progressive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/partial_progressive.jpg -------------------------------------------------------------------------------- /tests/reftest/images/partial_progressive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/partial_progressive.png -------------------------------------------------------------------------------- /tests/reftest/images/progressive-missing-ac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive-missing-ac.jpg -------------------------------------------------------------------------------- /tests/reftest/images/progressive-missing-ac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive-missing-ac.png -------------------------------------------------------------------------------- /tests/reftest/images/progressive-missing-dc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive-missing-dc.jpg -------------------------------------------------------------------------------- /tests/reftest/images/progressive-missing-dc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive-missing-dc.png -------------------------------------------------------------------------------- /tests/reftest/images/progressive3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive3.jpg -------------------------------------------------------------------------------- /tests/reftest/images/progressive3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/progressive3.png -------------------------------------------------------------------------------- /tests/reftest/images/restarts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/restarts.jpg -------------------------------------------------------------------------------- /tests/reftest/images/restarts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/restarts.png -------------------------------------------------------------------------------- /tests/reftest/images/rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/rgb.jpg -------------------------------------------------------------------------------- /tests/reftest/images/rgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/rgb.png -------------------------------------------------------------------------------- /tests/reftest/images/rgb_125x84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/rgb_125x84.png -------------------------------------------------------------------------------- /tests/reftest/images/rgb_250x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/rgb_250x167.png -------------------------------------------------------------------------------- /tests/reftest/images/rgb_63x42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/rgb_63x42.png -------------------------------------------------------------------------------- /tests/reftest/images/ycck.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/ycck.jpg -------------------------------------------------------------------------------- /tests/reftest/images/ycck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-rs/jpeg-decoder/95550d7eec747b94b5f9beba3be2c6fcb1f4f70e/tests/reftest/images/ycck.png -------------------------------------------------------------------------------- /tests/reftest/mod.rs: -------------------------------------------------------------------------------- 1 | use jpeg; 2 | use png; 3 | use std::cmp; 4 | use std::fs::File; 5 | use std::path::Path; 6 | 7 | use super::common; 8 | 9 | #[test] 10 | fn reftest() { 11 | let files = common::test_files(&Path::new("tests").join("reftest").join("images")); 12 | 13 | for path in &files { 14 | reftest_file(path); 15 | } 16 | } 17 | 18 | #[test] 19 | fn reftest_scaled() { 20 | let base = &Path::new("tests").join("reftest").join("images"); 21 | reftest_scaled_file(&base.join("rgb.jpg"), 500, 333, &base.join("rgb.png")); 22 | reftest_scaled_file(&base.join("rgb.jpg"), 250, 167, &base.join("rgb_250x167.png")); 23 | reftest_scaled_file(&base.join("rgb.jpg"), 125, 84, &base.join("rgb_125x84.png")); 24 | reftest_scaled_file(&base.join("rgb.jpg"), 63, 42, &base.join("rgb_63x42.png")); 25 | } 26 | 27 | fn reftest_file(path: &Path) { 28 | let file = File::open(path).unwrap(); 29 | let decoder = jpeg::Decoder::new(file); 30 | reftest_decoder(decoder, path, &path.with_extension("png")); 31 | } 32 | 33 | fn reftest_scaled_file(path: &Path, width: u16, height: u16, ref_path: &Path) { 34 | let file = File::open(path).unwrap(); 35 | let mut decoder = jpeg::Decoder::new(file); 36 | decoder.read_info().unwrap(); 37 | decoder.scale(width, height).unwrap(); 38 | reftest_decoder(decoder, path, &ref_path); 39 | } 40 | 41 | fn reftest_decoder(mut decoder: jpeg::Decoder, path: &Path, ref_path: &Path) { 42 | let mut data = decoder.decode().expect(&format!("failed to decode file: {:?}", path)); 43 | let info = decoder.info().unwrap(); 44 | let mut pixel_format = info.pixel_format; 45 | 46 | if pixel_format == jpeg::PixelFormat::CMYK32 { 47 | data = cmyk_to_rgb(&data); 48 | pixel_format = jpeg::PixelFormat::RGB24; 49 | } 50 | 51 | let ref_file = File::open(ref_path).unwrap(); 52 | let mut decoder = png::Decoder::new(ref_file); 53 | 54 | if pixel_format == jpeg::PixelFormat::L16 { 55 | // disable the default 8bit output of png v0.16.8 (fixed in master branch of png) 56 | decoder.set_transformations(png::Transformations::EXPAND); 57 | } 58 | 59 | let (ref_info, mut ref_reader) = decoder.read_info().expect("png failed to read info"); 60 | 61 | assert_eq!(ref_info.width, info.width as u32); 62 | assert_eq!(ref_info.height, info.height as u32); 63 | 64 | let mut ref_data = vec![0; ref_info.buffer_size()]; 65 | ref_reader.next_frame(&mut ref_data).expect("png decode failed"); 66 | let mut ref_pixel_format = ref_info.color_type; 67 | 68 | if ref_pixel_format == png::ColorType::RGBA { 69 | ref_data = rgba_to_rgb(&ref_data); 70 | ref_pixel_format = png::ColorType::RGB; 71 | } 72 | 73 | let (refdata_16, data_u16) : (Vec, Vec) = match pixel_format { 74 | jpeg::PixelFormat::L8 => { 75 | assert_eq!(ref_pixel_format, png::ColorType::Grayscale); 76 | assert_eq!(ref_info.bit_depth, png::BitDepth::Eight); 77 | (ref_data.iter().map(|x| *x as u16).collect(), data.iter().map(|x| *x as u16).collect()) 78 | }, 79 | jpeg::PixelFormat::L16 => { 80 | assert_eq!(ref_pixel_format, png::ColorType::Grayscale); 81 | assert_eq!(ref_info.bit_depth, png::BitDepth::Sixteen); 82 | (ref_data.chunks_exact(2).map(|a| u16::from_be_bytes([a[0],a[1]])).collect(), 83 | data.chunks_exact(2).map(|a| u16::from_ne_bytes([a[0],a[1]])).collect()) 84 | }, 85 | jpeg::PixelFormat::RGB24 => { 86 | assert_eq!(ref_pixel_format, png::ColorType::RGB); 87 | assert_eq!(ref_info.bit_depth, png::BitDepth::Eight); 88 | (ref_data.iter().map(|x| *x as u16).collect(), data.iter().map(|x| *x as u16).collect()) 89 | }, 90 | _ => panic!(), 91 | }; 92 | 93 | assert_eq!(data_u16.len(), refdata_16.len()); 94 | let mut max_diff = 0; 95 | let pixels: Vec = data_u16.iter().zip(refdata_16.iter()).map(|(&a, &b)| { 96 | let diff = (a as isize - b as isize).abs(); 97 | max_diff = cmp::max(diff, max_diff); 98 | 99 | if (info.coding_process != jpeg::CodingProcess::Lossless && diff <= 3) || diff == 0 { 100 | // White for correct 101 | 0xFF 102 | } else { 103 | // "1100" in the RGBA channel with an error for an incorrect value 104 | // This results in some number of C0 and FFs, which is much more 105 | // readable (and distinguishable) than the previous difference-wise 106 | // scaling but does not require reconstructing the actual RGBA pixel. 107 | 0xC0 108 | } 109 | }).collect(); 110 | 111 | if pixels.iter().any(|&a| a < 255) { 112 | let output_path = path.with_file_name(format!("{}-diff.png", path.file_stem().unwrap().to_str().unwrap())); 113 | let output = File::create(&output_path).unwrap(); 114 | let mut encoder = png::Encoder::new(output, info.width as u32, info.height as u32); 115 | encoder.set_depth(png::BitDepth::Eight); 116 | encoder.set_color(ref_pixel_format); 117 | encoder.write_header().expect("png failed to write header").write_image_data(&pixels).expect("png failed to write data"); 118 | 119 | panic!("decoding difference: {output_path:?}, maximum difference was {max_diff}"); 120 | } 121 | } 122 | 123 | fn rgba_to_rgb(input: &[u8]) -> Vec { 124 | let size = input.len() - input.len() / 4; 125 | let mut output = Vec::with_capacity(size); 126 | 127 | for pixel in input.chunks(4) { 128 | assert_eq!(pixel[3], 255); 129 | 130 | output.push(pixel[0]); 131 | output.push(pixel[1]); 132 | output.push(pixel[2]); 133 | } 134 | 135 | output 136 | } 137 | 138 | fn cmyk_to_rgb(input: &[u8]) -> Vec { 139 | let size = input.len() - input.len() / 4; 140 | let mut output = Vec::with_capacity(size); 141 | 142 | for pixel in input.chunks(4) { 143 | let c = pixel[0] as f32 / 255.0; 144 | let m = pixel[1] as f32 / 255.0; 145 | let y = pixel[2] as f32 / 255.0; 146 | let k = pixel[3] as f32 / 255.0; 147 | 148 | // CMYK -> CMY 149 | let c = c * (1.0 - k) + k; 150 | let m = m * (1.0 - k) + k; 151 | let y = y * (1.0 - k) + k; 152 | 153 | // CMY -> RGB 154 | let r = (1.0 - c) * 255.0; 155 | let g = (1.0 - m) * 255.0; 156 | let b = (1.0 - y) * 255.0; 157 | 158 | output.push(r as u8); 159 | output.push(g as u8); 160 | output.push(b as u8); 161 | } 162 | 163 | output 164 | } 165 | --------------------------------------------------------------------------------