summaryrefslogtreecommitdiff
path: root/Libraries/LibGfx
diff options
context:
space:
mode:
authorPeter Nelson <peter@peterdn.com>2020-08-29 15:04:41 +0100
committerAndreas Kling <kling@serenityos.org>2020-08-30 10:27:36 +0200
commit1341025da7eefa5dd6cfbf572cc70eed30a9a562 (patch)
tree693cc1cf12eeff97ea8d7f8500cfd37c739b7495 /Libraries/LibGfx
parent3ae55770c8326f20f9ebb431111b88499c231159 (diff)
downloadserenity-1341025da7eefa5dd6cfbf572cc70eed30a9a562.zip
LibGfx: correctly handle GIF frame disposal modes
RestoreBackground disposal mode is now a transparent fill to allow background to show through. RestorePrevious disposal mode now restores the previous frame.
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r--Libraries/LibGfx/GIFLoader.cpp25
1 files changed, 17 insertions, 8 deletions
diff --git a/Libraries/LibGfx/GIFLoader.cpp b/Libraries/LibGfx/GIFLoader.cpp
index c3796cc06d..9580582c93 100644
--- a/Libraries/LibGfx/GIFLoader.cpp
+++ b/Libraries/LibGfx/GIFLoader.cpp
@@ -260,6 +260,15 @@ private:
Vector<u8> m_output {};
};
+static void copy_frame(Bitmap& destination, Bitmap& source)
+{
+ for (int y = 0; y < source.height(); ++y) {
+ for (int x = 0; x < source.width(); ++x) {
+ destination.set_pixel(x, y, source.get_pixel(x, y));
+ }
+ }
+}
+
static bool decode_frames_up_to_index(GIFLoadingContext& context, size_t frame_index)
{
if (frame_index >= context.images.size()) {
@@ -285,18 +294,18 @@ static bool decode_frames_up_to_index(GIFLoadingContext& context, size_t frame_i
image.bitmap = Bitmap::create_purgeable(BitmapFormat::RGBA32, { context.logical_screen.width, context.logical_screen.height });
+ if (i == 0) {
+ image.bitmap->fill(background_color);
+ }
+
const auto previous_image_disposal_method = i > 0 ? context.images.at(i - 1).disposal_method : ImageDescriptor::DisposalMethod::None;
- if (previous_image_disposal_method == ImageDescriptor::DisposalMethod::InPlace) {
- for (int y = 0; y < image.bitmap->height(); ++y) {
- for (int x = 0; x < image.bitmap->width(); ++x) {
- image.bitmap->set_pixel(x, y, context.images.at(i - 1).bitmap->get_pixel(x, y));
- }
- }
+ if (i > 0 && (previous_image_disposal_method == ImageDescriptor::DisposalMethod::None || previous_image_disposal_method == ImageDescriptor::DisposalMethod::InPlace)) {
+ copy_frame(*image.bitmap, *context.images.at(i - 1).bitmap);
} else if (previous_image_disposal_method == ImageDescriptor::DisposalMethod::RestoreBackground) {
- image.bitmap->fill(background_color);
- } else if (previous_image_disposal_method == ImageDescriptor::DisposalMethod::RestorePrevious) {
image.bitmap->fill(Color(Color::NamedColor::Transparent));
+ } else if (i > 1 && previous_image_disposal_method == ImageDescriptor::DisposalMethod::RestorePrevious) {
+ copy_frame(*image.bitmap, *context.images.at(i - 2).bitmap);
}
int pixel_index = 0;