Serenity Operating System
1/*
2 * Copyright (c) 2022, Dex♪ <dexes.ttp@gmail.com>
3 * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#define AK_DONT_REPLACE_STD
9
10#include "ImageCodecPluginLadybird.h"
11#include <LibGfx/Bitmap.h>
12#include <LibGfx/ImageDecoder.h>
13#include <QImage>
14
15namespace Ladybird {
16
17ImageCodecPluginLadybird::~ImageCodecPluginLadybird() = default;
18
19static Optional<Web::Platform::DecodedImage> decode_image_with_qt(ReadonlyBytes data)
20{
21 auto image = QImage::fromData(data.data(), static_cast<int>(data.size()));
22 if (image.isNull())
23 return {};
24 image = image.convertToFormat(QImage::Format::Format_ARGB32);
25 auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(image.width(), image.height())));
26 for (int y = 0; y < image.height(); ++y) {
27 memcpy(bitmap->scanline_u8(y), image.scanLine(y), image.width() * 4);
28 }
29 Vector<Web::Platform::Frame> frames;
30
31 frames.append(Web::Platform::Frame {
32 bitmap,
33 });
34 return Web::Platform::DecodedImage {
35 false,
36 0,
37 move(frames),
38 };
39}
40
41static Optional<Web::Platform::DecodedImage> decode_image_with_libgfx(ReadonlyBytes data)
42{
43 auto decoder = Gfx::ImageDecoder::try_create_for_raw_bytes(data);
44
45 if (!decoder || !decoder->frame_count()) {
46 return {};
47 }
48
49 bool had_errors = false;
50 Vector<Web::Platform::Frame> frames;
51 for (size_t i = 0; i < decoder->frame_count(); ++i) {
52 auto frame_or_error = decoder->frame(i);
53 if (frame_or_error.is_error()) {
54 frames.append({ {}, 0 });
55 had_errors = true;
56 } else {
57 auto frame = frame_or_error.release_value();
58 frames.append({ move(frame.image), static_cast<size_t>(frame.duration) });
59 }
60 }
61
62 if (had_errors)
63 return {};
64
65 return Web::Platform::DecodedImage {
66 decoder->is_animated(),
67 static_cast<u32>(decoder->loop_count()),
68 move(frames),
69 };
70}
71
72Optional<Web::Platform::DecodedImage> ImageCodecPluginLadybird::decode_image(ReadonlyBytes data)
73{
74 auto image = decode_image_with_libgfx(data);
75 if (image.has_value())
76 return image;
77 return decode_image_with_qt(data);
78}
79
80}