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:
parent
cc4184cb47
commit
508ae37c6e
1 changed files with 26 additions and 14 deletions
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue