diff options
author | Peter Nelson <peter@peterdn.com> | 2020-08-29 16:05:24 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-30 10:27:36 +0200 |
commit | 786872e4c9f3fea255af763b914058c1bcc434b5 (patch) | |
tree | 7c797723af50c763cd841628e542f4118de84b50 /Libraries/LibGfx/GIFLoader.cpp | |
parent | 1341025da7eefa5dd6cfbf572cc70eed30a9a562 (diff) | |
download | serenity-786872e4c9f3fea255af763b914058c1bcc434b5.zip |
LibGfx: add support for interlaced GIFs
Diffstat (limited to 'Libraries/LibGfx/GIFLoader.cpp')
-rw-r--r-- | Libraries/LibGfx/GIFLoader.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/Libraries/LibGfx/GIFLoader.cpp b/Libraries/LibGfx/GIFLoader.cpp index 9580582c93..773f3e7283 100644 --- a/Libraries/LibGfx/GIFLoader.cpp +++ b/Libraries/LibGfx/GIFLoader.cpp @@ -42,12 +42,17 @@ struct RGB { u8 b; }; +// Row strides and offsets for each interlace pass. +static const int INTERLACE_ROW_STRIDES[] = { 8, 8, 4, 2 }; +static const int INTERLACE_ROW_OFFSETS[] = { 0, 4, 2, 1 }; + struct ImageDescriptor { u16 x { 0 }; u16 y { 0 }; u16 width { 0 }; u16 height { 0 }; bool use_global_color_map { true }; + bool interlaced { false }; RGB color_map[256]; u8 lzw_min_code_size { 0 }; Vector<u8> lzw_encoded_bytes; @@ -309,6 +314,8 @@ static bool decode_frames_up_to_index(GIFLoadingContext& context, size_t frame_i } int pixel_index = 0; + int row = 0; + int interlace_pass = 0; while (true) { Optional<u16> code = decoder.next_code(); if (!code.has_value()) { @@ -329,7 +336,7 @@ static bool decode_frames_up_to_index(GIFLoadingContext& context, size_t frame_i auto rgb = color_map[color]; int x = pixel_index % image.width + image.x; - int y = pixel_index / image.width + image.y; + int y = row + image.y; Color c = Color(rgb.r, rgb.g, rgb.b); @@ -342,6 +349,18 @@ static bool decode_frames_up_to_index(GIFLoadingContext& context, size_t frame_i } ++pixel_index; + if (pixel_index % image.width == 0) { + if (image.interlaced) { + if (row + INTERLACE_ROW_STRIDES[interlace_pass] >= image.height) { + ++interlace_pass; + row = INTERLACE_ROW_OFFSETS[interlace_pass]; + } else { + row += INTERLACE_ROW_STRIDES[interlace_pass]; + } + } else { + ++row; + } + } } } @@ -506,6 +525,7 @@ static bool load_gif_frame_descriptors(GIFLoadingContext& context) return false; image.use_global_color_map = !(packed_fields & 0x80); + image.interlaced = (packed_fields & 0x40) != 0; if (!image.use_global_color_map) { size_t local_color_table_size = pow(2, (packed_fields & 7) + 1); |