| // Copyright 2023 The Wuffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // ---------------- |
| |
| /* |
| This test program is typically run indirectly, by the "wuffs test" or "wuffs |
| bench" commands. These commands take an optional "-mimic" flag to check that |
| Wuffs' output mimics (i.e. exactly matches) other libraries' output, such as |
| giflib for GIF, libpng for PNG, etc. |
| |
| To manually run this test: |
| |
| for CC in clang gcc; do |
| $CC -std=c99 -Wall -Werror jpeg.c && ./a.out |
| rm -f a.out |
| done |
| |
| Each edition should print "PASS", amongst other information, and exit(0). |
| |
| Add the "wuffs mimic cflags" (everything after the colon below) to the C |
| compiler flags (after the .c file) to run the mimic tests. |
| |
| To manually run the benchmarks, replace "-Wall -Werror" with "-O3" and replace |
| the first "./a.out" with "./a.out -bench". Combine these changes with the |
| "wuffs mimic cflags" to run the mimic benchmarks. |
| */ |
| |
| // ¿ wuffs mimic cflags: -DWUFFS_MIMIC |
| |
| // Wuffs ships as a "single file C library" or "header file library" as per |
| // https://github.com/nothings/stb/blob/master/docs/stb_howto.txt |
| // |
| // To use that single file as a "foo.c"-like implementation, instead of a |
| // "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or |
| // compiling it. |
| #define WUFFS_IMPLEMENTATION |
| |
| // Defining the WUFFS_CONFIG__MODULE* macros are optional, but it lets users of |
| // release/c/etc.c choose which parts of Wuffs to build. That file contains the |
| // entire Wuffs standard library, implementing a variety of codecs and file |
| // formats. Without this macro definition, an optimizing compiler or linker may |
| // very well discard Wuffs code for unused codecs, but listing the Wuffs |
| // modules we use makes that process explicit. Preprocessing means that such |
| // code simply isn't compiled. |
| #define WUFFS_CONFIG__MODULES |
| #define WUFFS_CONFIG__MODULE__BASE |
| #define WUFFS_CONFIG__MODULE__JPEG |
| |
| // If building this program in an environment that doesn't easily accommodate |
| // relative includes, you can use the script/inline-c-relative-includes.go |
| // program to generate a stand-alone C file. |
| #include "../../../release/c/wuffs-unsupported-snapshot.c" |
| #include "../testlib/testlib.c" |
| #ifdef WUFFS_MIMIC |
| // No mimic library. |
| #endif |
| |
| // ---------------- JPEG Tests |
| |
| const char* // |
| wuffs_jpeg_decode(uint64_t* n_bytes_out, |
| wuffs_base__io_buffer* dst, |
| uint32_t wuffs_initialize_flags, |
| wuffs_base__pixel_format pixfmt, |
| uint32_t* quirks_ptr, |
| size_t quirks_len, |
| wuffs_base__io_buffer* src) { |
| wuffs_jpeg__decoder dec; |
| CHECK_STATUS("initialize", |
| wuffs_jpeg__decoder__initialize(&dec, sizeof dec, WUFFS_VERSION, |
| wuffs_initialize_flags)); |
| return do_run__wuffs_base__image_decoder( |
| wuffs_jpeg__decoder__upcast_as__wuffs_base__image_decoder(&dec), |
| n_bytes_out, dst, pixfmt, quirks_ptr, quirks_len, src); |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_interface() { |
| CHECK_FOCUS(__func__); |
| wuffs_jpeg__decoder dec; |
| CHECK_STATUS("initialize", |
| wuffs_jpeg__decoder__initialize( |
| &dec, sizeof dec, WUFFS_VERSION, |
| WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); |
| return do_test__wuffs_base__image_decoder( |
| wuffs_jpeg__decoder__upcast_as__wuffs_base__image_decoder(&dec), |
| "test/data/bricks-color.jpeg", 0, SIZE_MAX, 160, 120, 0xFF012466); |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_truncated_input() { |
| CHECK_FOCUS(__func__); |
| |
| wuffs_base__io_buffer src = |
| wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false); |
| wuffs_jpeg__decoder dec; |
| CHECK_STATUS("initialize", |
| wuffs_jpeg__decoder__initialize( |
| &dec, sizeof dec, WUFFS_VERSION, |
| WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); |
| |
| wuffs_base__status status = |
| wuffs_jpeg__decoder__decode_image_config(&dec, NULL, &src); |
| if (status.repr != wuffs_base__suspension__short_read) { |
| RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr, |
| wuffs_base__suspension__short_read); |
| } |
| |
| src.meta.closed = true; |
| status = wuffs_jpeg__decoder__decode_image_config(&dec, NULL, &src); |
| if (status.repr != wuffs_jpeg__error__truncated_input) { |
| RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr, |
| wuffs_jpeg__error__truncated_input); |
| } |
| return NULL; |
| } |
| |
| const char* // |
| do_test_wuffs_jpeg_decode_dht(wuffs_base__io_buffer* src, |
| const uint32_t arg_bits, |
| const uint32_t arg_n_bits, |
| const int32_t* want_dst_ptr, |
| const size_t want_dst_len, |
| const uint8_t (*want_symbols)[256], |
| const uint32_t (*want_slow)[16], |
| const uint16_t (*want_fast)[256]) { |
| wuffs_jpeg__decoder dec; |
| memset(&dec, 0xAB, sizeof dec); // 0xAB is arbitrary, non-zero junk. |
| CHECK_STATUS("initialize", |
| wuffs_jpeg__decoder__initialize( |
| &dec, sizeof dec, WUFFS_VERSION, |
| WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED)); |
| |
| // Decode that DHT payload. |
| if (wuffs_base__io_buffer__reader_length(src) <= 0) { |
| return "empty src"; |
| } |
| uint32_t tc4_th = ((src->data.ptr[src->meta.ri] >> 2) & 0x04) | |
| ((src->data.ptr[src->meta.ri] >> 0) & 0x03); |
| dec.private_impl.f_sof_marker = 0xC0; |
| dec.private_impl.f_payload_length = |
| ((uint32_t)(wuffs_base__io_buffer__reader_length(src))); |
| CHECK_STATUS("decode_dht", wuffs_jpeg__decoder__decode_dht(&dec, src)); |
| |
| if (memcmp(dec.private_impl.f_huff_tables_symbols[tc4_th], want_symbols, |
| sizeof(*want_symbols))) { |
| RETURN_FAIL("unexpected huff_tables_symbols"); |
| } else if (memcmp(dec.private_impl.f_huff_tables_slow[tc4_th], want_slow, |
| sizeof(*want_slow))) { |
| RETURN_FAIL("unexpected huff_tables_slow"); |
| } else if (memcmp(dec.private_impl.f_huff_tables_fast[tc4_th], want_fast, |
| sizeof(*want_fast))) { |
| RETURN_FAIL("unexpected huff_tables_fast"); |
| } |
| |
| const int32_t err_not_enough_bits = -1; |
| const int32_t err_fast_not_applicable = -2; |
| const int32_t err_invalid_code = -3; |
| |
| // Check decoding of (arg_bits, arg_n_bits). |
| for (int use_fast = 0; use_fast < 2; use_fast++) { |
| uint32_t bits = arg_bits; |
| uint32_t n_bits = arg_n_bits; |
| for (size_t i = 0; i < want_dst_len; i++) { |
| int have = err_fast_not_applicable; |
| |
| if (use_fast) { |
| uint16_t x = (*want_fast)[bits >> 24]; |
| uint32_t n = x >> 8; |
| if (x == 0xFFFF) { |
| have = err_fast_not_applicable; |
| } else if (n > n_bits) { |
| have = err_not_enough_bits; |
| } else { |
| bits <<= n; |
| n_bits -= n; |
| have = x & 0xFF; |
| } |
| } |
| |
| if (have == err_fast_not_applicable) { |
| uint32_t code = 0; |
| for (uint32_t j = 0; true; j++) { |
| if (n_bits <= 0) { |
| have = err_not_enough_bits; |
| break; |
| } else if (j >= 16) { |
| have = err_invalid_code; |
| break; |
| } |
| code = (code << 1) | (bits >> 31); |
| bits <<= 1; |
| n_bits -= 1; |
| uint32_t x = (*want_slow)[j]; |
| if (code < (x >> 8)) { |
| have = (*want_symbols)[(code + x) & 0xFF]; |
| break; |
| } |
| } |
| } |
| |
| if (have != want_dst_ptr[i]) { |
| RETURN_FAIL("output symbols: use_fast=%d, i=%zu: have %d, want %d", |
| use_fast, i, have, want_dst_ptr[i]); |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_dht_easy() { |
| CHECK_FOCUS(__func__); |
| |
| const uint8_t want_symbols[256] = { |
| 6, 7, 4, 5, 0, 3, 8, 9, 2, 1, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // |
| }; |
| |
| // Set src to this fragment of "hd test/data/bricks-color.jpeg". |
| // 000000b0 .. ff c4 00 1d 00 00 02 02 03 01 01 01 00 00 00 |
| // 000000c0 00 00 00 00 00 00 06 07 04 05 00 03 08 09 02 01 |
| // The "ff c4" is the DHT marker. The "00 1d" is the payload length. The |
| // remaining payload has 0x001D - 2 = 0x1B = 17 + 10 bytes. |
| g_src_array_u8[0x00] = 0x00; // (tc, th) selectors are (0, 0). |
| g_src_array_u8[0x01] = 0x00; // 0 codes of bit_length 1. |
| g_src_array_u8[0x02] = 0x02; // 2 codes of bit_length 2. |
| g_src_array_u8[0x03] = 0x02; // 2 codes of bit_length 3. |
| g_src_array_u8[0x04] = 0x03; // 3 codes of bit_length 4. |
| g_src_array_u8[0x05] = 0x01; // 1 codes of bit_length 5. |
| g_src_array_u8[0x06] = 0x01; // 1 codes of bit_length 6. |
| g_src_array_u8[0x07] = 0x01; // 1 codes of bit_length 7. |
| g_src_array_u8[0x08] = 0x00; // 0 codes of bit_length 8. |
| g_src_array_u8[0x09] = 0x00; // 0 codes of bit_length 9. |
| g_src_array_u8[0x0A] = 0x00; // etc. |
| g_src_array_u8[0x0B] = 0x00; |
| g_src_array_u8[0x0C] = 0x00; |
| g_src_array_u8[0x0D] = 0x00; |
| g_src_array_u8[0x0E] = 0x00; |
| g_src_array_u8[0x0F] = 0x00; |
| g_src_array_u8[0x10] = 0x00; // 0 codes of bit-length 16. 10 codes total. |
| g_src_array_u8[0x11] = want_symbols[0]; // The 1st symbol is 0x06. |
| g_src_array_u8[0x12] = want_symbols[1]; // The 2nd symbol is 0x07. |
| g_src_array_u8[0x13] = want_symbols[2]; // The 3rd symbol is 0x04. |
| g_src_array_u8[0x14] = want_symbols[3]; // etc. |
| g_src_array_u8[0x15] = want_symbols[4]; |
| g_src_array_u8[0x16] = want_symbols[5]; |
| g_src_array_u8[0x17] = want_symbols[6]; |
| g_src_array_u8[0x18] = want_symbols[7]; |
| g_src_array_u8[0x19] = want_symbols[8]; |
| g_src_array_u8[0x1A] = want_symbols[9]; |
| wuffs_base__io_buffer src = |
| wuffs_base__ptr_u8__reader(g_src_array_u8, 0x1B, false); |
| |
| // The Huffman codes are: |
| // 0b00...... bit_length=2 symbol=6 |
| // 0b01...... bit_length=2 symbol=7 |
| // 0b100..... bit_length=3 symbol=4 |
| // 0b101..... bit_length=3 symbol=5 |
| // 0b1100.... bit_length=4 symbol=0 |
| // 0b1101.... bit_length=4 symbol=3 |
| // 0b1110.... bit_length=4 symbol=8 |
| // 0b11110... bit_length=5 symbol=9 |
| // 0b111110.. bit_length=6 symbol=2 |
| // 0b1111110. bit_length=7 symbol=1 |
| // 0b1111111. invalid |
| |
| // Running this on "wxyz" input should give these symbols: |
| // 0x77 'w' 0x78 'x' 0x79 'y' 0x7A 'z' |
| // 0b0111_0111 0b0111_1000 0b0111_1001 0b0111_1010 |
| // 01 1101 1101 1110 00 01 1110 01 01 1110 10 |
| // s7 s3 s3 s8 s6 s7 s8 s7 s7 s8 err_not_enough_bits |
| const uint32_t bits = 0x7778797A; |
| const uint32_t n_bits = 32; |
| const int32_t want_dst_ptr[11] = {7, 3, 3, 8, 6, 7, 8, 7, 7, 8, -1}; |
| const size_t want_dst_len = 11; |
| |
| const uint32_t want_slow[16] = { |
| 0x00000000, 0x00000200, 0x000006FE, 0x00000FF8, // |
| 0x00001FE9, 0x00003FCA, 0x00007F8B, 0x00000000, // |
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, // |
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, // |
| }; |
| |
| const uint16_t want_fast[256] = { |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, // |
| |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, 0x0207, // |
| |
| 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, // |
| 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, // |
| 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, // |
| 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, 0x0304, // |
| 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, // |
| 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, // |
| 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, // |
| 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, 0x0305, // |
| |
| 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, // |
| 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, // |
| 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, // |
| 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, 0x0403, // |
| 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, // |
| 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, 0x0408, // |
| 0x0509, 0x0509, 0x0509, 0x0509, 0x0509, 0x0509, 0x0509, 0x0509, // |
| 0x0602, 0x0602, 0x0602, 0x0602, 0x0701, 0x0701, 0xFFFF, 0xFFFF, // |
| }; |
| |
| return do_test_wuffs_jpeg_decode_dht(&src, bits, n_bits, want_dst_ptr, |
| want_dst_len, &want_symbols, &want_slow, |
| &want_fast); |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_dht_hard() { |
| CHECK_FOCUS(__func__); |
| |
| const uint8_t want_symbols[256] = { |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x00, 0x06, // |
| 0x07, 0x12, 0x21, 0x31, 0x13, 0x41, 0x51, 0x08, // |
| 0x14, 0x22, 0x61, 0x71, 0x32, 0x42, 0x81, 0x91, // |
| 0xA1, 0xB1, 0x15, 0x23, 0x52, 0x33, 0x82, 0xC1, // |
| 0xD1, 0xF0, 0x16, 0x62, 0x72, 0x92, 0xC2, 0xE1, // |
| 0x17, 0x53, 0x63, 0xA2, 0xA4, 0xB2, 0xF1, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // |
| }; |
| |
| // Set src to this fragment of "hd test/data/bricks-color.jpeg". |
| // 000000d0 ff c4 00 42 10 00 02 01 03 02 04 03 05 06 03 05 |
| // 000000e0 06 07 00 00 00 01 02 03 04 05 11 00 06 07 12 21 |
| // 000000f0 31 13 41 51 08 14 22 61 71 32 42 81 91 a1 b1 15 |
| // 00000100 23 52 33 82 c1 d1 f0 16 62 72 92 c2 e1 17 53 63 |
| // 00000110 a2 a4 b2 f1 .. .. .. .. .. .. .. .. .. .. .. .. |
| // The "ff c4" is the DHT marker. The "00 42" is the payload length. The |
| // remaining payload has 0x0042 - 2 = 0x40 = 17 + 47 bytes. |
| g_src_array_u8[0x00] = 0x10; // (tc, th) selectors are (1, 0). |
| g_src_array_u8[0x01] = 0x00; // 0 codes of bit_length 1. |
| g_src_array_u8[0x02] = 0x02; // 2 codes of bit_length 2. |
| g_src_array_u8[0x03] = 0x01; // 1 codes of bit_length 3. |
| g_src_array_u8[0x04] = 0x03; // 3 codes of bit_length 4. |
| g_src_array_u8[0x05] = 0x02; // 2 codes of bit_length 5. |
| g_src_array_u8[0x06] = 0x04; // 4 codes of bit_length 6. |
| g_src_array_u8[0x07] = 0x03; // 3 codes of bit_length 7. |
| g_src_array_u8[0x08] = 0x05; // 5 codes of bit_length 8. |
| g_src_array_u8[0x09] = 0x06; // 6 codes of bit_length 9. |
| g_src_array_u8[0x0A] = 0x03; // etc. |
| g_src_array_u8[0x0B] = 0x05; |
| g_src_array_u8[0x0C] = 0x06; |
| g_src_array_u8[0x0D] = 0x07; |
| g_src_array_u8[0x0E] = 0x00; |
| g_src_array_u8[0x0F] = 0x00; |
| g_src_array_u8[0x10] = 0x00; // 0 codes of bit-length 16. 47 codes total. |
| memcpy(&g_src_array_u8[0x11], want_symbols, 47); |
| wuffs_base__io_buffer src = |
| wuffs_base__ptr_u8__reader(g_src_array_u8, 0x40, false); |
| |
| // The Huffman codes are: |
| // 0b00......_........ bit_length=0x02 symbol=0x01 |
| // 0b01......_........ bit_length=0x02 symbol=0x02 |
| // 0b100....._........ bit_length=0x03 symbol=0x03 |
| // 0b1010...._........ bit_length=0x04 symbol=0x04 |
| // 0b1011...._........ bit_length=0x04 symbol=0x05 |
| // 0b1100...._........ bit_length=0x04 symbol=0x11 |
| // 0b11010..._........ bit_length=0x05 symbol=0x00 |
| // 0b11011..._........ bit_length=0x05 symbol=0x06 |
| // 0b111000.._........ bit_length=0x06 symbol=0x07 |
| // 0b111001.._........ bit_length=0x06 symbol=0x12 |
| // 0b111010.._........ bit_length=0x06 symbol=0x21 |
| // 0b111011.._........ bit_length=0x06 symbol=0x31 |
| // 0b1111000._........ bit_length=0x07 symbol=0x13 |
| // 0b1111001._........ bit_length=0x07 symbol=0x41 |
| // 0b1111010._........ bit_length=0x07 symbol=0x51 |
| // 0b11110110_........ bit_length=0x08 symbol=0x08 |
| // 0b11110111_........ bit_length=0x08 symbol=0x14 |
| // 0b11111000_........ bit_length=0x08 symbol=0x22 |
| // 0b11111001_........ bit_length=0x08 symbol=0x61 |
| // 0b11111010_........ bit_length=0x08 symbol=0x71 |
| // 0b11111011_0....... bit_length=0x09 symbol=0x32 |
| // 0b11111011_1....... bit_length=0x09 symbol=0x42 |
| // 0b11111100_0....... bit_length=0x09 symbol=0x81 |
| // 0b11111100_1....... bit_length=0x09 symbol=0x91 |
| // 0b11111101_0....... bit_length=0x09 symbol=0xA1 |
| // 0b11111101_1....... bit_length=0x09 symbol=0xB1 |
| // 0b11111110_00...... bit_length=0x0A symbol=0x15 |
| // 0b11111110_01...... bit_length=0x0A symbol=0x23 |
| // 0b11111110_10...... bit_length=0x0A symbol=0x52 |
| // 0b11111110_110..... bit_length=0x0B symbol=0x33 |
| // 0b11111110_111..... bit_length=0x0B symbol=0x82 |
| // 0b11111111_000..... bit_length=0x0B symbol=0xC1 |
| // 0b11111111_001..... bit_length=0x0B symbol=0xD1 |
| // 0b11111111_010..... bit_length=0x0B symbol=0xF0 |
| // 0b11111111_0110.... bit_length=0x0C symbol=0x16 |
| // 0b11111111_0111.... bit_length=0x0C symbol=0x62 |
| // 0b11111111_1000.... bit_length=0x0C symbol=0x72 |
| // 0b11111111_1001.... bit_length=0x0C symbol=0x92 |
| // 0b11111111_1010.... bit_length=0x0C symbol=0xC2 |
| // 0b11111111_1011.... bit_length=0x0C symbol=0xE1 |
| // 0b11111111_11000... bit_length=0x0D symbol=0x17 |
| // 0b11111111_11001... bit_length=0x0D symbol=0x53 |
| // 0b11111111_11010... bit_length=0x0D symbol=0x63 |
| // 0b11111111_11011... bit_length=0x0D symbol=0xA2 |
| // 0b11111111_11100... bit_length=0x0D symbol=0xA4 |
| // 0b11111111_11101... bit_length=0x0D symbol=0xB2 |
| // 0b11111111_11110... bit_length=0x0D symbol=0xF1 |
| // 0b11111111_11111... invalid |
| |
| // Running this on "wx\x7Fh" input should give these symbols: |
| // 0x77 'w' 0x78 'x' 0x7F '\x7F' 0x68 'h' |
| // 0b0111_0111 0b0111_1000 0b0111_1111 0b0110_1000 |
| // 01 11011 1011 1100 00 11111110110 100 0 |
| // s2 s6 s5 s11 s1 s33 s3 err_not_enough_bits |
| const uint32_t bits = 0x77787F68; |
| const uint32_t n_bits = 32; |
| const int32_t want_dst_ptr[8] = {0x02, 0x06, 0x05, 0x11, |
| 0x01, 0x33, 0x03, -1}; |
| const size_t want_dst_len = 8; |
| |
| const uint32_t want_slow[16] = { |
| 0x00000000, 0x00000200, 0x000005FE, 0x00000DF9, // |
| 0x00001CEC, 0x00003CD0, 0x00007B94, 0x0000FB19, // |
| 0x0001FC1E, 0x0003FB22, 0x0007FB27, 0x000FFC2C, // |
| 0x001FFF30, 0x00000000, 0x00000000, 0x00000000, // |
| }; |
| |
| const uint16_t want_fast[256] = { |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, // |
| |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, // |
| |
| 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, // |
| 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, // |
| 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, // |
| 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, // |
| 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, // |
| 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, // |
| 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, // |
| 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, 0x0405, // |
| |
| 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, // |
| 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, 0x0411, // |
| 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, // |
| 0x0506, 0x0506, 0x0506, 0x0506, 0x0506, 0x0506, 0x0506, 0x0506, // |
| 0x0607, 0x0607, 0x0607, 0x0607, 0x0612, 0x0612, 0x0612, 0x0612, // |
| 0x0621, 0x0621, 0x0621, 0x0621, 0x0631, 0x0631, 0x0631, 0x0631, // |
| 0x0713, 0x0713, 0x0741, 0x0741, 0x0751, 0x0751, 0x0808, 0x0814, // |
| 0x0822, 0x0861, 0x0871, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // |
| }; |
| |
| return do_test_wuffs_jpeg_decode_dht(&src, bits, n_bits, want_dst_ptr, |
| want_dst_len, &want_symbols, &want_slow, |
| &want_fast); |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_idct() { |
| CHECK_FOCUS(__func__); |
| |
| // This is "test/data/bricks-color.jpeg"'s first MCU's first block, in |
| // natural (not zig-zag) order. |
| const uint16_t mcu_block[64] = { |
| 0xFFC9, 0xFFD8, 0x0014, 0xFFF7, 0x0002, 0x0000, 0x0000, 0x0000, // |
| 0x006A, 0xFFE3, 0x001C, 0xFFF9, 0x0002, 0x0000, 0x0000, 0x0000, // |
| 0x0015, 0x0002, 0x0002, 0xFFFE, 0x0001, 0x0000, 0x0000, 0x0001, // |
| 0x000D, 0xFFEC, 0x0005, 0xFFFE, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0xFFFA, 0xFFFA, 0x0002, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0xFFFD, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }; |
| |
| // This is "test/data/bricks-color.jpeg"'s first quantization table, in |
| // natural (not zig-zag) order. |
| const uint8_t quant_table[64] = { |
| 0x03, 0x02, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0A, // |
| 0x02, 0x02, 0x02, 0x03, 0x04, 0x09, 0x0A, 0x09, // |
| 0x02, 0x02, 0x03, 0x04, 0x06, 0x09, 0x0B, 0x09, // |
| 0x02, 0x03, 0x04, 0x05, 0x08, 0x0E, 0x0D, 0x0A, // |
| 0x03, 0x04, 0x06, 0x09, 0x0B, 0x11, 0x10, 0x0C, // |
| 0x04, 0x06, 0x09, 0x0A, 0x0D, 0x11, 0x12, 0x0F, // |
| 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x13, 0x13, 0x10, // |
| 0x0C, 0x0F, 0x0F, 0x10, 0x12, 0x10, 0x10, 0x10, // |
| }; |
| |
| // This is the IDCT's expected result (including dequantization), again in |
| // natural (not zig-zag) order. |
| const uint8_t want_array[64] = { |
| 0x81, 0x7E, 0x82, 0x7E, 0x82, 0x92, 0xC5, 0xF2, // |
| 0x81, 0x80, 0x84, 0x85, 0x85, 0x88, 0x9D, 0xB2, // |
| 0x86, 0x81, 0x7A, 0x77, 0x72, 0x75, 0x7E, 0x8A, // |
| 0x54, 0x58, 0x58, 0x5E, 0x5E, 0x6C, 0x79, 0x87, // |
| 0x4D, 0x54, 0x56, 0x5B, 0x59, 0x65, 0x6E, 0x7A, // |
| 0x4A, 0x4D, 0x4F, 0x53, 0x56, 0x5F, 0x67, 0x6E, // |
| 0x4A, 0x4D, 0x54, 0x58, 0x5B, 0x58, 0x56, 0x54, // |
| 0x4C, 0x4C, 0x52, 0x4F, 0x4D, 0x40, 0x3A, 0x35, // |
| }; |
| |
| wuffs_jpeg__decoder dec; |
| CHECK_STATUS("initialize", wuffs_jpeg__decoder__initialize( |
| &dec, sizeof dec, WUFFS_VERSION, |
| WUFFS_INITIALIZE__DEFAULT_OPTIONS)); |
| |
| const uint32_t b = 0; |
| memcpy(&dec.private_data.f_mcu_blocks[b], mcu_block, sizeof(mcu_block)); |
| |
| const uint32_t q = 0; |
| memcpy(&dec.private_impl.f_quant_tables[q], quant_table, sizeof(quant_table)); |
| |
| uint8_t dst_array[64] = {0}; |
| wuffs_jpeg__decoder__decode_idct( |
| &dec, wuffs_base__make_slice_u8(&dst_array[0], 64), 8, b, q); |
| |
| wuffs_base__io_buffer have = |
| wuffs_base__ptr_u8__reader(&dst_array[0], 64, true); |
| wuffs_base__io_buffer want = |
| wuffs_base__ptr_u8__reader((void*)(&want_array[0]), 64, true); |
| |
| return check_io_buffers_equal("", &have, &want); |
| } |
| |
| const char* // |
| test_wuffs_jpeg_decode_mcu() { |
| CHECK_FOCUS(__func__); |
| |
| wuffs_base__io_buffer src = ((wuffs_base__io_buffer){ |
| .data = g_src_slice_u8, |
| }); |
| CHECK_STRING(read_file(&src, "test/data/bricks-color.jpeg")); |
| |
| wuffs_jpeg__decoder dec; |
| CHECK_STATUS("initialize", wuffs_jpeg__decoder__initialize( |
| &dec, sizeof dec, WUFFS_VERSION, |
| WUFFS_INITIALIZE__DEFAULT_OPTIONS)); |
| |
| // Bypass the "#missing Quantization table" check. |
| dec.private_impl.f_seen_dqt[0] = true; |
| dec.private_impl.f_seen_dqt[1] = true; |
| |
| // Decode the 0xC0 SOF marker, four 0xC4 DHT markers and 0xDA SOS marker. The |
| // SOS marker is only partially processed, since complete SOS processing |
| // would call wuffs_jpeg__decoder__decode_mcu multiple times. |
| const uint32_t marker_positions[6] = // |
| {0x09E, 0x0B1, 0x0D0, 0x114, 0x133, 0x16E}; |
| for (int i = 0; i < WUFFS_TESTLIB_ARRAY_SIZE(marker_positions); i++) { |
| uint8_t want_marker = (i <= 0) ? 0xC0 : ((i <= 4) ? 0xC4 : 0xDA); |
| src.meta.ri = marker_positions[i]; |
| if ((src.meta.ri + 4) > src.meta.wi) { |
| RETURN_FAIL("seek #%d: past EOF", i); |
| } else if (src.data.ptr[src.meta.ri++] != 0xFF) { |
| RETURN_FAIL("seek #%d: have 0x%02X, want 0x%02X", i, |
| src.data.ptr[src.meta.ri - 1], 0xFF); |
| } else if (src.data.ptr[src.meta.ri++] != want_marker) { |
| RETURN_FAIL("seek #%d: have 0x%02X, want 0x%02X", i, |
| src.data.ptr[src.meta.ri - 1], want_marker); |
| } |
| |
| dec.private_impl.f_payload_length = 0; |
| dec.private_impl.f_payload_length |= src.data.ptr[src.meta.ri++]; |
| dec.private_impl.f_payload_length <<= 8; |
| dec.private_impl.f_payload_length |= src.data.ptr[src.meta.ri++]; |
| dec.private_impl.f_payload_length -= 2; |
| |
| if (i <= 0) { |
| dec.private_impl.f_sof_marker = 0xC0; |
| CHECK_STATUS("decode_sof", wuffs_jpeg__decoder__decode_sof(&dec, &src)); |
| } else if (i <= 4) { |
| CHECK_STATUS("decode_dht", wuffs_jpeg__decoder__decode_dht(&dec, &src)); |
| } else { |
| CHECK_STATUS("prepare_scan", |
| wuffs_jpeg__decoder__prepare_scan(&dec, &src)); |
| wuffs_jpeg__decoder__fill_bitstream(&dec, &src); |
| } |
| } |
| |
| // Decode and compare-to-golden the first MCU (Minimum Coded Unit). |
| |
| if (wuffs_jpeg__decoder__decode_mcu(&dec)) { |
| RETURN_FAIL("decode_mcu failed"); |
| } |
| |
| // 4:2:0 chroma subsampling means that the MCU has 4 Y, 1 Cb and 1 Cr blocks. |
| uint16_t wants[10][64] = { |
| { |
| 0xFFC9, 0xFFD8, 0x0014, 0xFFF7, 0x0002, 0x0000, 0x0000, 0x0000, // |
| 0x006A, 0xFFE3, 0x001C, 0xFFF9, 0x0002, 0x0000, 0x0000, 0x0000, // |
| 0x0015, 0x0002, 0x0002, 0xFFFE, 0x0001, 0x0000, 0x0000, 0x0001, // |
| 0x000D, 0xFFEC, 0x0005, 0xFFFE, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0xFFFA, 0xFFFA, 0x0002, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0xFFFD, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }, |
| { |
| 0xFFAA, 0x0070, 0x003A, 0xFFE0, 0xFFF9, 0x0004, 0x0000, 0x0001, // |
| 0x004F, 0x005E, 0x0022, 0x0006, 0xFFF3, 0xFFFD, 0x0004, 0x0000, // |
| 0xFFF4, 0xFFE8, 0x0002, 0x0012, 0x0003, 0x0000, 0xFFFF, 0x0002, // |
| 0xFFEC, 0xFFF3, 0x000A, 0x000A, 0x0007, 0x0000, 0xFFFF, 0xFFFF, // |
| 0xFFF3, 0xFFFB, 0xFFFD, 0x0002, 0x0002, 0x0000, 0x0001, 0x0000, // |
| 0xFFFC, 0xFFFB, 0xFFFD, 0xFFFF, 0x0000, 0x0002, 0x0001, 0x0001, // |
| 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, // |
| 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0001, 0x0000, // |
| }, |
| { |
| 0xFF25, 0x000D, 0x0003, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x000E, 0x0006, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0005, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0004, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }, |
| { |
| 0xFF59, 0xFFD6, 0xFFCF, 0x000C, 0x0006, 0xFFFE, 0xFFFE, 0x0002, // |
| 0xFFF3, 0x0013, 0x000C, 0xFFE6, 0x000E, 0x0001, 0xFFFC, 0x0004, // |
| 0x0010, 0xFFF1, 0x0005, 0x0003, 0xFFFA, 0x0002, 0x0001, 0xFFFE, // |
| 0xFFF9, 0x0005, 0x0000, 0xFFFE, 0x0002, 0x0000, 0xFFFE, 0x0002, // |
| 0x0003, 0xFFFF, 0x0000, 0x0001, 0xFFFF, 0x0000, 0x0001, 0xFFFF, // |
| 0xFFFE, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }, |
| { |
| 0x0077, 0x000F, 0xFFFA, 0x0001, 0x0000, 0xFFFF, 0x0002, 0xFFFF, // |
| 0xFFFA, 0x0020, 0xFFF9, 0x0000, 0x0000, 0xFFFF, 0x0001, 0xFFFF, // |
| 0xFFFA, 0x0008, 0x0000, 0x0000, 0xFFFF, 0x0001, 0x0000, 0x0000, // |
| 0xFFFE, 0x0001, 0x0001, 0x0001, 0xFFFF, 0x0001, 0xFFFF, 0x0000, // |
| 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }, |
| { |
| 0xFF88, 0x0003, 0xFFFD, 0x0000, 0x0000, 0x0000, 0xFFFF, 0x0001, // |
| 0xFFE4, 0xFFEC, 0x0001, 0x0001, 0x0000, 0x0001, 0xFFFF, 0x0001, // |
| 0xFFFC, 0xFFFC, 0xFFFE, 0x0000, 0x0001, 0xFFFF, 0x0000, 0x0000, // |
| 0x0001, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0xFFFF, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0xFFFE, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // |
| }, |
| {0}, // |
| {0}, // |
| {0}, // |
| {0}, // |
| }; |
| |
| for (int b = 0; b < 10; b++) { |
| wuffs_base__io_buffer have = wuffs_base__ptr_u8__reader( // |
| (void*)(&dec.private_data.f_mcu_blocks[b]), // |
| sizeof(dec.private_data.f_mcu_blocks[b]), true); |
| wuffs_base__io_buffer want = wuffs_base__ptr_u8__reader( // |
| (void*)(&wants[b]), // |
| sizeof(wants[b]), true); |
| |
| char prefix[64]; |
| snprintf(prefix, 64, "b=%d: ", b); |
| CHECK_STRING(check_io_buffers_equal(prefix, &have, &want)); |
| } |
| |
| return NULL; |
| } |
| |
| // ---------------- Mimic Tests |
| |
| #ifdef WUFFS_MIMIC |
| |
| // No mimic tests. |
| |
| #endif // WUFFS_MIMIC |
| |
| // ---------------- JPEG Benches |
| |
| const char* // |
| bench_wuffs_jpeg_decode_77k_24bpp() { |
| CHECK_FOCUS(__func__); |
| return do_bench_image_decode( |
| &wuffs_jpeg_decode, |
| WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, |
| wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL), |
| NULL, 0, "test/data/bricks-color.jpeg", 0, SIZE_MAX, 1000); |
| } |
| |
| // ---------------- Mimic Benches |
| |
| #ifdef WUFFS_MIMIC |
| |
| // No mimic benches. |
| |
| #endif // WUFFS_MIMIC |
| |
| // ---------------- Manifest |
| |
| proc g_tests[] = { |
| |
| test_wuffs_jpeg_decode_dht_easy, |
| test_wuffs_jpeg_decode_dht_hard, |
| test_wuffs_jpeg_decode_idct, |
| test_wuffs_jpeg_decode_mcu, |
| test_wuffs_jpeg_decode_interface, |
| test_wuffs_jpeg_decode_truncated_input, |
| |
| #ifdef WUFFS_MIMIC |
| |
| // No mimic tests. |
| |
| #endif // WUFFS_MIMIC |
| |
| NULL, |
| }; |
| |
| proc g_benches[] = { |
| |
| bench_wuffs_jpeg_decode_77k_24bpp, |
| |
| #ifdef WUFFS_MIMIC |
| |
| // No mimic benches. |
| |
| #endif // WUFFS_MIMIC |
| |
| NULL, |
| }; |
| |
| int // |
| main(int argc, char** argv) { |
| g_proc_package_name = "std/jpeg"; |
| return test_main(argc, argv, g_tests, g_benches); |
| } |