1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 21:27:34 +00:00

LibGfx: Move scan-related information to its own struct

Putting them directly in the context isn't good for neither readability,
comprehension nor spec compliance.
This commit is contained in:
Lucas CHOLLET 2023-02-22 19:41:29 -05:00 committed by Andreas Kling
parent cc4184cb47
commit 508ae37c6e

View file

@ -177,6 +177,14 @@ struct ICCMultiChunkState {
FixedArray<ByteBuffer> chunks; FixedArray<ByteBuffer> chunks;
}; };
struct Scan {
// B.2.3 - Scan header syntax
u8 spectral_selection_start {};
u8 spectral_selection_end {};
u8 successive_approximation {};
};
struct JPEGLoadingContext { struct JPEGLoadingContext {
enum State { enum State {
NotDecoded = 0, NotDecoded = 0,
@ -194,9 +202,9 @@ struct JPEGLoadingContext {
StartOfFrame frame; StartOfFrame frame;
u8 hsample_factor { 0 }; u8 hsample_factor { 0 };
u8 vsample_factor { 0 }; u8 vsample_factor { 0 };
u8 spectral_selection_start {};
u8 spectral_selection_end {}; Scan current_scan;
u8 successive_approximation {};
Vector<ComponentSpec, 3> components; Vector<ComponentSpec, 3> components;
RefPtr<Gfx::Bitmap> bitmap; RefPtr<Gfx::Bitmap> bitmap;
u16 dc_restart_interval { 0 }; u16 dc_restart_interval { 0 };
@ -308,9 +316,9 @@ static ErrorOr<void> add_ac(JPEGLoadingContext& context, Macroblock& macroblock,
// Compute the AC coefficients. // Compute the AC coefficients.
// 0th coefficient is the dc, which is already handled // 0th coefficient is the dc, which is already handled
auto first_coefficient = max(1, context.spectral_selection_start); auto first_coefficient = max(1, context.current_scan.spectral_selection_start);
for (int j = first_coefficient; j <= context.spectral_selection_end;) { for (int j = first_coefficient; j <= context.current_scan.spectral_selection_end;) {
// AC symbols encode 2 pieces of information, the high 4 bits represent // AC symbols encode 2 pieces of information, the high 4 bits represent
// number of zeroes to be stuffed before reading the coefficient. Low 4 // number of zeroes to be stuffed before reading the coefficient. Low 4
// bits represent the magnitude of the coefficient. // bits represent the magnitude of the coefficient.
@ -322,7 +330,7 @@ static ErrorOr<void> add_ac(JPEGLoadingContext& context, Macroblock& macroblock,
u8 run_length = ac_symbol == 0xF0 ? 16 : ac_symbol >> 4; u8 run_length = ac_symbol == 0xF0 ? 16 : ac_symbol >> 4;
j += run_length; j += run_length;
if (j > context.spectral_selection_end) { if (j > context.current_scan.spectral_selection_end) {
dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", j, run_length); dbgln_if(JPEG_DEBUG, "Run-length exceeded boundaries. Cursor: {}, Skipping: {}!", j, run_length);
return Error::from_string_literal("Run-length exceeded boundaries"); return Error::from_string_literal("Run-length exceeded boundaries");
} }
@ -375,7 +383,7 @@ static ErrorOr<void> build_macroblocks(JPEGLoadingContext& context, Vector<Macro
u32 mb_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor); u32 mb_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor);
Macroblock& block = macroblocks[mb_index]; Macroblock& block = macroblocks[mb_index];
if (context.spectral_selection_start == 0) if (context.current_scan.spectral_selection_start == 0)
TRY(add_dc(context, block, component, component_i)); TRY(add_dc(context, block, component, component_i));
TRY(add_ac(context, block, component, component_i)); TRY(add_ac(context, block, component, component_i));
} }
@ -572,20 +580,24 @@ static ErrorOr<void> read_start_of_scan(AK::SeekableStream& stream, JPEGLoadingC
return Error::from_string_literal("AC table does not exist"); return Error::from_string_literal("AC table does not exist");
} }
} }
Scan current_scan;
context.spectral_selection_start = TRY(stream.read_value<u8>()); current_scan.spectral_selection_start = TRY(stream.read_value<u8>());
context.spectral_selection_end = TRY(stream.read_value<u8>()); current_scan.spectral_selection_end = TRY(stream.read_value<u8>());
context.successive_approximation = TRY(stream.read_value<u8>()); current_scan.successive_approximation = TRY(stream.read_value<u8>());
// The three values should be fixed for baseline JPEGs utilizing sequential DCT. // The three values should be fixed for baseline JPEGs utilizing sequential DCT.
if (context.spectral_selection_start != 0 || context.spectral_selection_end != 63 || context.successive_approximation != 0) { if (current_scan.spectral_selection_start != 0 || current_scan.spectral_selection_end != 63 || current_scan.successive_approximation != 0) {
dbgln_if(JPEG_DEBUG, "{}: ERROR! Start of Selection: {}, End of Selection: {}, Successive Approximation: {}!", dbgln_if(JPEG_DEBUG, "{}: ERROR! Start of Selection: {}, End of Selection: {}, Successive Approximation: {}!",
TRY(stream.tell()), TRY(stream.tell()),
context.spectral_selection_start, current_scan.spectral_selection_start,
context.spectral_selection_end, current_scan.spectral_selection_end,
context.successive_approximation); current_scan.successive_approximation);
return Error::from_string_literal("Spectral selection is not [0,63] or successive approximation is not null"); return Error::from_string_literal("Spectral selection is not [0,63] or successive approximation is not null");
} }
context.current_scan = current_scan;
return {}; return {};
} }