瀏覽代碼

LibGfx: Add first_animated_frame_index method to ImageDecoder

Some image formats such as APNG may not use the first frame for
animations.
Tom 2 年之前
父節點
當前提交
e7921cfe14

+ 6 - 4
Userland/Libraries/LibGUI/ImageWidget.cpp

@@ -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();
         }
     }

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/BMPLoader.cpp

@@ -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)

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/BMPLoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/DDSLoader.cpp

@@ -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)

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/DDSLoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/GIFLoader.cpp

@@ -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) {

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/GIFLoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/ICOLoader.cpp

@@ -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)

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/ICOLoader.h

@@ -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;
 

+ 2 - 0
Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.h

@@ -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(); }
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp

@@ -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)

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/PNGLoader.cpp

@@ -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)

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/PNGLoader.h

@@ -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;
 

+ 7 - 0
Userland/Libraries/LibGfx/ImageFormats/PortableImageMapLoader.h

@@ -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)
 {

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/QOILoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/TGALoader.cpp

@@ -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;

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/TGALoader.h

@@ -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;
 

+ 5 - 0
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp

@@ -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())

+ 1 - 0
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.h

@@ -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;