diff options
-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 {}; |