Skip to content

Commit

Permalink
LibGfx: Add first_animated_frame_index method to ImageDecoder
Browse files Browse the repository at this point in the history
Some image formats such as APNG may not use the first frame for
animations.
  • Loading branch information
tomuta authored and AtkinsSJ committed May 5, 2023
1 parent 5a4c618 commit e7921cf
Show file tree
Hide file tree
Showing 20 changed files with 64 additions and 4 deletions.
10 changes: 6 additions & 4 deletions Userland/Libraries/LibGUI/ImageWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/BMPLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/BMPLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class BMPImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/DDSLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/DDSLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class DDSImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/GIFLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/GIFLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GIFImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/ICOLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/ICOLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ICOImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ImageDecoderPlugin {
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;

Expand All @@ -59,6 +60,7 @@ class ImageDecoder : public RefCounted<ImageDecoder> {
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(); }

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class JPEGImageDecoderPlugin : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/PNGLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/PNGLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PNGImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class PortableImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/QOILoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class QOIImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/TGALoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/TGALoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class TGAImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down
5 changes: 5 additions & 0 deletions Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibGfx/ImageFormats/WebPLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class WebPImageDecoderPlugin final : public ImageDecoderPlugin {
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;

Expand Down

0 comments on commit e7921cf

Please sign in to comment.