summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorLucas CHOLLET <lucas.chollet@free.fr>2023-02-26 01:45:00 -0500
committerLinus Groh <mail@linusgroh.de>2023-04-03 17:06:21 +0100
commit731c876ff7cedddd428d6ffe9625983eef84e0bf (patch)
treed803a4c2d8c80f3738ccd76a26e454ff100a42a5 /Userland/Libraries
parent902d0ab58e5b022c6b1ba9816fee9d77def2c747 (diff)
downloadserenity-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.cpp48
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 {};