1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:48:14 +00:00

LibGfx: Add first_animated_frame_index method to ImageDecoder

Some image formats such as APNG may not use the first frame for
animations.
This commit is contained in:
Tom 2023-04-07 20:41:22 -06:00 committed by Sam Atkins
parent 5a4c61838f
commit e7921cfe14
20 changed files with 64 additions and 4 deletions

View file

@ -52,18 +52,20 @@ void ImageWidget::set_auto_resize(bool value)
// Same as ImageViewer::ViewWidget::animate(), you probably want to keep any changes in sync
void ImageWidget::animate()
{
m_current_frame_index = (m_current_frame_index + 1) % m_image_decoder->frame_count();
auto first_animated_frame_index = m_image_decoder->first_animated_frame_index();
auto total_animated_frames = m_image_decoder->frame_count() - first_animated_frame_index;
m_current_frame_index = (m_current_frame_index + 1) % total_animated_frames;
auto current_frame = m_image_decoder->frame(m_current_frame_index).release_value_but_fixme_should_propagate_errors();
auto current_frame = m_image_decoder->frame(first_animated_frame_index + m_current_frame_index).release_value_but_fixme_should_propagate_errors();
set_bitmap(current_frame.image);
if (current_frame.duration != m_timer->interval()) {
m_timer->restart(current_frame.duration);
}
if (m_current_frame_index == m_image_decoder->frame_count() - 1) {
if (m_current_frame_index == total_animated_frames - 1) {
++m_loops_completed;
if (m_loops_completed > 0 && m_loops_completed == m_image_decoder->loop_count()) {
if (m_image_decoder->loop_count() > 0 && m_loops_completed == m_image_decoder->loop_count()) {
m_timer->stop();
}
}

View file

@ -1544,6 +1544,11 @@ size_t BMPImageDecoderPlugin::frame_count()
return 1;
}
size_t BMPImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> BMPImageDecoderPlugin::frame(size_t index)
{
if (index > 0)

View file

@ -35,6 +35,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -685,6 +685,11 @@ size_t DDSImageDecoderPlugin::frame_count()
return 1;
}
size_t DDSImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> DDSImageDecoderPlugin::frame(size_t index)
{
if (index > 0)

View file

@ -247,6 +247,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -627,6 +627,11 @@ size_t GIFImageDecoderPlugin::frame_count()
return m_context->images.size();
}
size_t GIFImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> GIFImageDecoderPlugin::frame(size_t index)
{
if (m_context->error_state >= GIFLoadingContext::ErrorState::FailedToDecodeAnyFrame) {

View file

@ -27,6 +27,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -251,6 +251,11 @@ size_t ICOImageDecoderPlugin::frame_count()
return 1;
}
size_t ICOImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> ICOImageDecoderPlugin::frame(size_t index)
{
if (index > 0)

View file

@ -26,6 +26,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -39,6 +39,7 @@ public:
virtual bool is_animated() = 0;
virtual size_t loop_count() = 0;
virtual size_t frame_count() = 0;
virtual size_t first_animated_frame_index() = 0;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) = 0;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() = 0;
@ -59,6 +60,7 @@ public:
bool is_animated() const { return m_plugin->is_animated(); }
size_t loop_count() const { return m_plugin->loop_count(); }
size_t frame_count() const { return m_plugin->frame_count(); }
size_t first_animated_frame_index() const { return m_plugin->first_animated_frame_index(); }
ErrorOr<ImageFrameDescriptor> frame(size_t index) const { return m_plugin->frame(index); }
ErrorOr<Optional<ReadonlyBytes>> icc_data() const { return m_plugin->icc_data(); }

View file

@ -1801,6 +1801,11 @@ size_t JPEGImageDecoderPlugin::frame_count()
return 1;
}
size_t JPEGImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> JPEGImageDecoderPlugin::frame(size_t index)
{
if (index > 0)

View file

@ -29,6 +29,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -1062,6 +1062,11 @@ size_t PNGImageDecoderPlugin::frame_count()
return 1;
}
size_t PNGImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> PNGImageDecoderPlugin::frame(size_t index)
{
if (index > 0)

View file

@ -26,6 +26,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -71,6 +71,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;
@ -160,6 +161,12 @@ size_t PortableImageDecoderPlugin<TContext>::frame_count()
return 1;
}
template<typename TContext>
size_t PortableImageDecoderPlugin<TContext>::first_animated_frame_index()
{
return 0;
}
template<typename TContext>
ErrorOr<ImageFrameDescriptor> PortableImageDecoderPlugin<TContext>::frame(size_t index)
{

View file

@ -50,6 +50,7 @@ public:
virtual bool is_animated() override { return false; }
virtual size_t loop_count() override { return 0; }
virtual size_t frame_count() override { return 1; }
virtual size_t first_animated_frame_index() override { return 0; }
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -257,6 +257,11 @@ size_t TGAImageDecoderPlugin::frame_count()
return 1;
}
size_t TGAImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index)
{
auto bits_per_pixel = m_context->header.bits_per_pixel;

View file

@ -27,6 +27,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;

View file

@ -1555,6 +1555,11 @@ size_t WebPImageDecoderPlugin::frame_count()
return m_context->animation_frame_chunks.size();
}
size_t WebPImageDecoderPlugin::first_animated_frame_index()
{
return 0;
}
ErrorOr<ImageFrameDescriptor> WebPImageDecoderPlugin::frame(size_t index)
{
if (index >= frame_count())

View file

@ -26,6 +26,7 @@ public:
virtual bool is_animated() override;
virtual size_t loop_count() override;
virtual size_t frame_count() override;
virtual size_t first_animated_frame_index() override;
virtual ErrorOr<ImageFrameDescriptor> frame(size_t index) override;
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;