diff options
author | Lucas CHOLLET <lucas.chollet@free.fr> | 2023-02-26 01:45:00 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-04-03 17:06:21 +0100 |
commit | 731c876ff7cedddd428d6ffe9625983eef84e0bf (patch) | |
tree | d803a4c2d8c80f3738ccd76a26e454ff100a42a5 /Userland/Libraries | |
parent | 902d0ab58e5b022c6b1ba9816fee9d77def2c747 (diff) | |
download | serenity-731c876ff7cedddd428d6ffe9625983eef84e0bf.zip |
LibGfx/JPEG: Change the loop over AC coefficients
We used to skip over zero coefficient by modifying the loop counter. It
is unfortunately impossible to perform this with SOF2 images as only
coefficients with a zero-history should be skipped.
This induces no behavior change for the user of the function.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp index 0f462e2450..8ecae9cbb4 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp @@ -365,11 +365,9 @@ static ErrorOr<bool> read_eob(Scan& scan, u32 symbol) scan.end_of_bands_run_count = additional_value + (1 << eob_base) - 1; - if (scan.end_of_bands_run_count >= 1) { - // end_of_bands_run_count is decremented at the end of `build_macroblocks`. - // This line compensate this effect. - ++scan.end_of_bands_run_count; - } + // end_of_bands_run_count is decremented at the end of `build_macroblocks`. + // And we need to now that we reached End of Block in `add_ac`. + ++scan.end_of_bands_run_count; return true; } @@ -395,28 +393,29 @@ static ErrorOr<void> add_ac(JPEGLoadingContext& context, Macroblock& macroblock, // 0th coefficient is the dc, which is already handled auto first_coefficient = max(1, scan.spectral_selection_start); - for (int j = first_coefficient; j <= scan.spectral_selection_end;) { - if (scan.end_of_bands_run_count > 0) - continue; - + u32 to_skip = 0; + Optional<u8> saved_symbol; + for (int j = first_coefficient; j <= scan.spectral_selection_end; ++j) { // AC symbols encode 2 pieces of information, the high 4 bits represent // number of zeroes to be stuffed before reading the coefficient. Low 4 // bits represent the magnitude of the coefficient. - auto ac_symbol = TRY(get_next_symbol(scan.huffman_stream, ac_table)); + if (scan.end_of_bands_run_count == 0 && !saved_symbol.has_value()) { + saved_symbol = TRY(get_next_symbol(scan.huffman_stream, ac_table)); - if (TRY(read_eob(scan, ac_symbol))) - break; - - // ac_symbol = JPEG_ZRL means we need to skip 16 zeroes. - u8 run_length = ac_symbol == JPEG_ZRL ? 16 : ac_symbol >> 4; - j += run_length; + if (!TRY(read_eob(scan, *saved_symbol))) { + to_skip = *saved_symbol >> 4; + } + } - if (j > scan.spectral_selection_end) { - dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", j, run_length); - return Error::from_string_literal("Run-length exceeded boundaries"); + if (to_skip > 0) { + --to_skip; + continue; } - u8 coeff_length = ac_symbol & 0x0F; + if (scan.end_of_bands_run_count > 0) + continue; + + u8 coeff_length = *saved_symbol & 0x0F; if (coeff_length > 10) { dbgln_if(JPEG_DEBUG, "AC coefficient too long: {}!", coeff_length); return Error::from_string_literal("AC coefficient too long"); @@ -427,8 +426,15 @@ static ErrorOr<void> add_ac(JPEGLoadingContext& context, Macroblock& macroblock, if (ac_coefficient < (1 << (coeff_length - 1))) ac_coefficient -= (1 << coeff_length) - 1; - select_component[zigzag_map[j++]] = ac_coefficient; + select_component[zigzag_map[j]] = ac_coefficient; } + + saved_symbol.clear(); + } + + if (to_skip > 0) { + dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", scan.spectral_selection_end + to_skip, to_skip); + return Error::from_string_literal("Run-length exceeded boundaries"); } return {}; |