summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGfx
diff options
context:
space:
mode:
authorLucas CHOLLET <lucas.chollet@free.fr>2023-02-19 23:37:30 -0500
committerAndreas Kling <kling@serenityos.org>2023-02-22 09:22:45 +0100
commitbae37676c24bc9f28ce2afbca5915820b55809c1 (patch)
treed687b95eed3a7ebacca264639a9f210dfca30896 /Userland/Libraries/LibGfx
parentc0c48afe062f6715db3a9106ef65818b575c2772 (diff)
downloadserenity-bae37676c24bc9f28ce2afbca5915820b55809c1.zip
LibGfx: Prepare the decoder to handle multiples scans
This means that we should read markers in a loop instead of quiting on the first scan. This is useless for now as `SOF0` frames only have one scan, but this is a step forward `SOF2` support.
Diffstat (limited to 'Userland/Libraries/LibGfx')
-rw-r--r--Userland/Libraries/LibGfx/JPEGLoader.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/Userland/Libraries/LibGfx/JPEGLoader.cpp b/Userland/Libraries/LibGfx/JPEGLoader.cpp
index ce060d95da..69c1a623ae 100644
--- a/Userland/Libraries/LibGfx/JPEGLoader.cpp
+++ b/Userland/Libraries/LibGfx/JPEGLoader.cpp
@@ -1184,9 +1184,7 @@ static ErrorOr<void> parse_header(AK::SeekableStream& stream, JPEGLoadingContext
case JPEG_SOF0:
TRY(read_start_of_frame(stream, context));
context.state = JPEGLoadingContext::FrameDecoded;
- break;
- case JPEG_SOS:
- return read_start_of_scan(stream, context);
+ return {};
default:
if (auto result = skip_segment(stream); result.is_error()) {
dbgln_if(JPEG_DEBUG, "{}: Error skipping marker: {:x}!", TRY(stream.tell()), marker);
@@ -1248,11 +1246,33 @@ static ErrorOr<void> decode_header(JPEGLoadingContext& context)
return {};
}
+static ErrorOr<Vector<Macroblock>> construct_macroblocks(JPEGLoadingContext& context)
+{
+ // B.6 - Summary
+ // See: Figure B.16 – Flow of compressed data syntax
+ // This function handles the "Multi-scan" loop.
+
+ Marker marker = TRY(read_marker_at_cursor(*context.stream));
+ while (true) {
+ if (is_miscellaneous_or_table_marker(marker)) {
+ TRY(handle_miscellaneous_or_table(*context.stream, context, marker));
+ } else if (marker == JPEG_SOS) {
+ TRY(read_start_of_scan(*context.stream, context));
+ TRY(scan_huffman_stream(*context.stream, context));
+ return TRY(decode_huffman_stream(context));
+ } else {
+ dbgln_if(JPEG_DEBUG, "{}: Unexpected marker {:x}!", TRY(context.stream->tell()), marker);
+ return Error::from_string_literal("Unexpected marker");
+ }
+
+ marker = TRY(read_marker_at_cursor(*context.stream));
+ }
+}
+
static ErrorOr<void> decode_jpeg(JPEGLoadingContext& context)
{
TRY(decode_header(context));
- TRY(scan_huffman_stream(*context.stream, context));
- auto macroblocks = TRY(decode_huffman_stream(context));
+ auto macroblocks = TRY(construct_macroblocks(context));
dequantize(context, macroblocks);
inverse_dct(context, macroblocks);
ycbcr_to_rgb(context, macroblocks);