1- use std:: io:: { BufRead , Read , Seek } ;
1+ use std:: io:: { BufRead , Seek } ;
22use std:: num:: NonZeroU32 ;
33
44use image_webp:: LoopCount ;
55
6- use crate :: buffer:: ConvertBuffer ;
7- use crate :: error:: { DecodingError , ImageError , ImageResult } ;
8- use crate :: io:: decoder:: DecodedMetadataHint ;
9- use crate :: io:: { DecodedImageAttributes , DecoderAttributes } ;
10- use crate :: {
11- AnimationDecoder , ColorType , Delay , Frame , Frames , ImageDecoder , ImageFormat , RgbImage , Rgba ,
12- RgbaImage ,
6+ use crate :: error:: { DecodingError , ImageError , ImageResult , ParameterError , ParameterErrorKind } ;
7+ use crate :: io:: {
8+ DecodedAnimationAttributes , DecodedImageAttributes , DecodedMetadataHint , DecoderAttributes ,
9+ SequenceControl ,
1310} ;
11+ use crate :: { ColorType , Delay , ImageDecoder , ImageFormat , Rgba } ;
1412
1513/// WebP Image format decoder.
1614///
1715/// Supports both lossless and lossy WebP images.
1816pub struct WebPDecoder < R > {
1917 inner : image_webp:: WebPDecoder < R > ,
18+ current : u32 ,
2019}
2120
2221impl < R : BufRead + Seek > WebPDecoder < R > {
2322 /// Create a new `WebPDecoder` from the Reader `r`.
2423 pub fn new ( r : R ) -> ImageResult < Self > {
2524 Ok ( Self {
2625 inner : image_webp:: WebPDecoder :: new ( r) . map_err ( ImageError :: from_webp_decode) ?,
26+ current : 0 ,
2727 } )
2828 }
2929
@@ -52,6 +52,17 @@ impl<R: BufRead + Seek> ImageDecoder for WebPDecoder<R> {
5252 }
5353 }
5454
55+ fn animation_attributes ( & mut self ) -> Option < DecodedAnimationAttributes > {
56+ let loop_count = match self . inner . loop_count ( ) {
57+ LoopCount :: Forever => crate :: metadata:: LoopCount :: Infinite ,
58+ LoopCount :: Times ( n) => crate :: metadata:: LoopCount :: Finite (
59+ NonZeroU32 :: new ( n. get ( ) . into ( ) ) . expect ( "LoopCount::Times should be non-zero" ) ,
60+ ) ,
61+ } ;
62+
63+ Some ( DecodedAnimationAttributes { loop_count } )
64+ }
65+
5566 fn peek_layout ( & mut self ) -> ImageResult < crate :: ImageLayout > {
5667 let ( width, height) = self . inner . dimensions ( ) ;
5768
@@ -67,14 +78,35 @@ impl<R: BufRead + Seek> ImageDecoder for WebPDecoder<R> {
6778 }
6879
6980 fn read_image ( & mut self , buf : & mut [ u8 ] ) -> ImageResult < DecodedImageAttributes > {
81+ let is_animated = self . inner . is_animated ( ) ;
82+
83+ if is_animated && self . current == self . inner . num_frames ( ) {
84+ return Err ( ImageError :: Parameter ( ParameterError :: from_kind (
85+ ParameterErrorKind :: NoMoreData ,
86+ ) ) ) ;
87+ }
88+
7089 let layout = self . peek_layout ( ) ?;
7190 assert_eq ! ( u64 :: try_from( buf. len( ) ) , Ok ( layout. total_bytes( ) ) ) ;
7291
73- self . inner
74- . read_image ( buf)
75- . map_err ( ImageError :: from_webp_decode) ?;
92+ // `read_frame` panics if the image is not animated.
93+ let delay = if is_animated {
94+ let delay = self
95+ . inner
96+ . read_frame ( buf)
97+ . map_err ( ImageError :: from_webp_decode) ?;
98+ Some ( Delay :: from_numer_denom_ms ( delay, 1 ) )
99+ } else {
100+ self . inner
101+ . read_image ( buf)
102+ . map_err ( ImageError :: from_webp_decode) ?;
103+ None
104+ } ;
105+
106+ self . current += 1 ;
76107
77108 Ok ( DecodedImageAttributes {
109+ delay,
78110 ..DecodedImageAttributes :: default ( )
79111 } )
80112 }
@@ -99,69 +131,23 @@ impl<R: BufRead + Seek> ImageDecoder for WebPDecoder<R> {
99131 . xmp_metadata ( )
100132 . map_err ( ImageError :: from_webp_decode)
101133 }
102- }
103134
104- impl < ' a , R : ' a + BufRead + Seek > AnimationDecoder < ' a > for WebPDecoder < R > {
105- fn loop_count ( & self ) -> crate :: metadata:: LoopCount {
106- match self . inner . loop_count ( ) {
107- LoopCount :: Forever => crate :: metadata:: LoopCount :: Infinite ,
108- LoopCount :: Times ( n) => crate :: metadata:: LoopCount :: Finite (
109- NonZeroU32 :: new ( n. get ( ) . into ( ) ) . expect ( "LoopCount::Times should be non-zero" ) ,
110- ) ,
135+ fn more_images ( & self ) -> SequenceControl {
136+ if self . current == self . inner . num_frames ( ) {
137+ SequenceControl :: None
138+ } else {
139+ SequenceControl :: MaybeMore
111140 }
112141 }
113-
114- fn into_frames ( self ) -> Frames < ' a > {
115- struct FramesInner < R : Read + Seek > {
116- decoder : WebPDecoder < R > ,
117- current : u32 ,
118- }
119- impl < R : BufRead + Seek > Iterator for FramesInner < R > {
120- type Item = ImageResult < Frame > ;
121-
122- fn next ( & mut self ) -> Option < Self :: Item > {
123- if self . current == self . decoder . inner . num_frames ( ) {
124- return None ;
125- }
126- self . current += 1 ;
127- let ( width, height) = self . decoder . inner . dimensions ( ) ;
128-
129- let ( img, delay) = if self . decoder . inner . has_alpha ( ) {
130- let mut img = RgbaImage :: new ( width, height) ;
131- match self . decoder . inner . read_frame ( & mut img) {
132- Ok ( delay) => ( img, delay) ,
133- Err ( image_webp:: DecodingError :: NoMoreFrames ) => return None ,
134- Err ( e) => return Some ( Err ( ImageError :: from_webp_decode ( e) ) ) ,
135- }
136- } else {
137- let mut img = RgbImage :: new ( width, height) ;
138- match self . decoder . inner . read_frame ( & mut img) {
139- Ok ( delay) => ( img. convert ( ) , delay) ,
140- Err ( image_webp:: DecodingError :: NoMoreFrames ) => return None ,
141- Err ( e) => return Some ( Err ( ImageError :: from_webp_decode ( e) ) ) ,
142- }
143- } ;
144-
145- Some ( Ok ( Frame :: from_parts (
146- img,
147- 0 ,
148- 0 ,
149- Delay :: from_numer_denom_ms ( delay, 1 ) ,
150- ) ) )
151- }
152- }
153-
154- Frames :: new ( Box :: new ( FramesInner {
155- decoder : self ,
156- current : 0 ,
157- } ) )
158- }
159142}
160143
161144impl ImageError {
162145 fn from_webp_decode ( e : image_webp:: DecodingError ) -> Self {
163146 match e {
164147 image_webp:: DecodingError :: IoError ( e) => ImageError :: IoError ( e) ,
148+ image_webp:: DecodingError :: NoMoreFrames => {
149+ ImageError :: Parameter ( ParameterError :: from_kind ( ParameterErrorKind :: NoMoreData ) )
150+ }
165151 _ => ImageError :: Decoding ( DecodingError :: new ( ImageFormat :: WebP . into ( ) , e) ) ,
166152 }
167153 }
0 commit comments