mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20:52:45 +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:
		
							parent
							
								
									5a4c61838f
								
							
						
					
					
						commit
						e7921cfe14
					
				
					 20 changed files with 64 additions and 4 deletions
				
			
		|  | @ -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(); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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(); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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()) | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tom
						Tom