Ladybird: Try decoding images with Qt if LibGfx fails us

We might as well ask Qt if it can decode images in case our own decoders
don't succeed.
This commit is contained in:
Andreas Kling 2022-07-26 20:17:12 +02:00 committed by Andrew Kaster
parent 11e5be050f
commit da23456f9e
Notes: sideshowbarker 2024-07-17 02:46:49 +09:00

View file

@ -833,6 +833,59 @@ void WebView::resizeEvent(QResizeEvent* event)
m_page_client->set_viewport_rect(rect);
}
static Optional<Web::ImageDecoding::DecodedImage> decode_image_with_qt(ReadonlyBytes data)
{
auto image = QImage::fromData(data.data(), static_cast<int>(data.size()));
if (image.isNull())
return {};
image = image.convertToFormat(QImage::Format::Format_ARGB32);
auto bitmap = MUST(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(image.width(), image.height())));
for (int y = 0; y < image.height(); ++y) {
memcpy(bitmap->scanline_u8(y), image.scanLine(y), image.width() * 4);
}
Vector<Web::ImageDecoding::Frame> frames;
frames.append(Web::ImageDecoding::Frame {
bitmap,
});
return Web::ImageDecoding::DecodedImage {
false,
0,
move(frames),
};
}
static Optional<Web::ImageDecoding::DecodedImage> decode_image_with_libgfx(ReadonlyBytes data)
{
auto decoder = Gfx::ImageDecoder::try_create(data);
if (!decoder || !decoder->frame_count()) {
return {};
}
bool had_errors = false;
Vector<Web::ImageDecoding::Frame> frames;
for (size_t i = 0; i < decoder->frame_count(); ++i) {
auto frame_or_error = decoder->frame(i);
if (frame_or_error.is_error()) {
frames.append({ {}, 0 });
had_errors = true;
} else {
auto frame = frame_or_error.release_value();
frames.append({ move(frame.image), static_cast<size_t>(frame.duration) });
}
}
if (had_errors)
return {};
return Web::ImageDecoding::DecodedImage {
decoder->is_animated(),
static_cast<u32>(decoder->loop_count()),
move(frames),
};
}
class HeadlessImageDecoderClient : public Web::ImageDecoding::Decoder {
public:
static NonnullRefPtr<HeadlessImageDecoderClient> create()
@ -844,30 +897,10 @@ public:
virtual Optional<Web::ImageDecoding::DecodedImage> decode_image(ReadonlyBytes data) override
{
auto decoder = Gfx::ImageDecoder::try_create(data);
if (!decoder)
return Web::ImageDecoding::DecodedImage { false, 0, Vector<Web::ImageDecoding::Frame> {} };
if (!decoder->frame_count())
return Web::ImageDecoding::DecodedImage { false, 0, Vector<Web::ImageDecoding::Frame> {} };
Vector<Web::ImageDecoding::Frame> frames;
for (size_t i = 0; i < decoder->frame_count(); ++i) {
auto frame_or_error = decoder->frame(i);
if (frame_or_error.is_error()) {
frames.append({ {}, 0 });
} else {
auto frame = frame_or_error.release_value();
frames.append({ move(frame.image), static_cast<size_t>(frame.duration) });
}
}
return Web::ImageDecoding::DecodedImage {
decoder->is_animated(),
static_cast<u32>(decoder->loop_count()),
frames,
};
auto image = decode_image_with_libgfx(data);
if (image.has_value())
return image;
return decode_image_with_qt(data);
}
private: