1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-11 18:20:43 +09:00

LibGfx/JPEG: Support up to 4 quantization tables

We used to limit this number to two and name them with their usual
usage. The specification is however broader, and you can find files that
use more tables as in the following link:

20050519/tests/A_2_1-BF-01.htm
This commit is contained in:
Lucas CHOLLET 2023-04-21 21:12:00 -04:00 committed by Andreas Kling
parent f46e3e6644
commit dd5d2e3505
Notes: sideshowbarker 2024-07-17 01:13:25 +09:00

View file

@ -237,8 +237,8 @@ struct JPEGLoadingContext {
State state { State::NotDecoded };
u32 luma_table[64] = { 0 };
u32 chroma_table[64] = { 0 };
Array<Optional<Array<u16, 64>>, 4> quantization_tables {};
StartOfFrame frame;
u8 hsample_factor { 0 };
u8 vsample_factor { 0 };
@ -1064,10 +1064,6 @@ static ErrorOr<void> read_start_of_frame(Stream& stream, JPEGLoadingContext& con
}
component.qtable_id = TRY(stream.read_value<u8>());
if (component.qtable_id > 1) {
dbgln_if(JPEG_DEBUG, "Unsupported quantization table id: {}!", component.qtable_id);
return Error::from_string_literal("Unsupported quantization table id");
}
context.components.append(move(component));
}
@ -1077,6 +1073,8 @@ static ErrorOr<void> read_start_of_frame(Stream& stream, JPEGLoadingContext& con
static ErrorOr<void> read_quantization_table(Stream& stream, JPEGLoadingContext& context)
{
// B.2.4.1 - Quantization table-specification syntax
u16 bytes_to_read = TRY(stream.read_value<BigEndian<u16>>()) - 2;
while (bytes_to_read > 0) {
u8 const info_byte = TRY(stream.read_value<u8>());
@ -1086,11 +1084,19 @@ static ErrorOr<void> read_quantization_table(Stream& stream, JPEGLoadingContext&
return Error::from_string_literal("Unsupported unit hint in quantization table");
}
u8 const table_id = info_byte & 0x0F;
if (table_id > 1) {
if (table_id > 3) {
dbgln_if(JPEG_DEBUG, "Unsupported quantization table id: {}!", table_id);
return Error::from_string_literal("Unsupported quantization table id");
}
u32* const table = table_id == 0 ? context.luma_table : context.chroma_table;
auto& maybe_table = context.quantization_tables[table_id];
if (!maybe_table.has_value())
maybe_table = Array<u16, 64> {};
auto& table = maybe_table.value();
for (int i = 0; i < 64; i++) {
if (element_unit_hint == 0)
table[zigzag_map[i]] = TRY(stream.read_value<u8>());
@ -1115,13 +1121,20 @@ static ErrorOr<void> skip_segment(Stream& stream)
return {};
}
static void dequantize(JPEGLoadingContext& context, Vector<Macroblock>& macroblocks)
static ErrorOr<void> dequantize(JPEGLoadingContext& context, Vector<Macroblock>& macroblocks)
{
for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.vsample_factor) {
for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.hsample_factor) {
for (u32 i = 0; i < context.components.size(); i++) {
auto& component = context.components[i];
u32 const* table = component.qtable_id == 0 ? context.luma_table : context.chroma_table;
auto const& component = context.components[i];
if (!context.quantization_tables[component.qtable_id].has_value()) {
dbgln_if(JPEG_DEBUG, "Unknown quantization table id: {}!", component.qtable_id);
return Error::from_string_literal("Unknown quantization table id");
}
auto const& table = context.quantization_tables[component.qtable_id].value();
for (u32 vfactor_i = 0; vfactor_i < component.vsample_factor; vfactor_i++) {
for (u32 hfactor_i = 0; hfactor_i < component.hsample_factor; hfactor_i++) {
u32 macroblock_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor);
@ -1134,6 +1147,8 @@ static void dequantize(JPEGLoadingContext& context, Vector<Macroblock>& macroblo
}
}
}
return {};
}
static void inverse_dct(JPEGLoadingContext const& context, Vector<Macroblock>& macroblocks)
@ -1706,7 +1721,7 @@ static ErrorOr<void> decode_jpeg(JPEGLoadingContext& context)
{
TRY(decode_header(context));
auto macroblocks = TRY(construct_macroblocks(context));
dequantize(context, macroblocks);
TRY(dequantize(context, macroblocks));
inverse_dct(context, macroblocks);
TRY(handle_color_transform(context, macroblocks));
TRY(compose_bitmap(context, macroblocks));