@@ -101,19 +101,34 @@ impl Into<DynamicImage> for &AnimFrame<'_> {
101
101
}
102
102
}
103
103
pub struct AnimEncoder < ' a > {
104
- frames : Vec < AnimFrame < ' a > > ,
105
104
width : u32 ,
106
105
height : u32 ,
107
106
config : & ' a WebPConfig ,
107
+ mux_abi_version : i32 ,
108
108
muxparams : WebPMuxAnimParams ,
109
+ encoder : * mut WebPAnimEncoder ,
109
110
}
110
111
impl < ' a > AnimEncoder < ' a > {
111
112
pub fn new ( width : u32 , height : u32 , config : & ' a WebPConfig ) -> Self {
113
+ let mut uninit = std:: mem:: MaybeUninit :: < WebPAnimEncoderOptions > :: uninit ( ) ;
114
+
115
+ let mux_abi_version = WebPGetMuxABIVersion ( ) ;
116
+ let encoder = unsafe {
117
+ WebPAnimEncoderOptionsInitInternal ( uninit. as_mut_ptr ( ) , mux_abi_version) ;
118
+ WebPAnimEncoderNewInternal (
119
+ width as i32 ,
120
+ height as i32 ,
121
+ uninit. as_ptr ( ) ,
122
+ mux_abi_version,
123
+ )
124
+ } ;
125
+
112
126
Self {
113
- frames : vec ! [ ] ,
114
127
width,
115
128
height,
116
129
config,
130
+ encoder,
131
+ mux_abi_version,
117
132
muxparams : WebPMuxAnimParams {
118
133
bgcolor : 0 ,
119
134
loop_count : 0 ,
@@ -130,14 +145,59 @@ impl<'a> AnimEncoder<'a> {
130
145
pub fn set_loop_count ( & mut self , loop_count : i32 ) {
131
146
self . muxparams . loop_count = loop_count;
132
147
}
133
- pub fn add_frame ( & mut self , frame : AnimFrame < ' a > ) {
134
- self . frames . push ( frame) ;
148
+ pub fn add_frame ( & mut self , frame : AnimFrame < ' _ > ) -> Result < ( ) , AnimEncodeError > {
149
+ unsafe {
150
+ let mut pic = crate :: new_picture ( frame. image , frame. layout , self . width , self . height ) ;
151
+ let config = frame. config . unwrap_or ( self . config ) ;
152
+ let ok = WebPAnimEncoderAdd (
153
+ self . encoder ,
154
+ & mut * pic as * mut _ ,
155
+ frame. timestamp as std:: os:: raw:: c_int ,
156
+ config,
157
+ ) ;
158
+ if ok == 0 {
159
+ return Err ( AnimEncodeError :: WebPEncodingError ( pic. error_code ) ) ;
160
+ }
161
+ }
162
+
163
+ Ok ( ( ) )
135
164
}
136
165
pub fn encode ( & self ) -> WebPMemory {
137
166
self . try_encode ( ) . unwrap ( )
138
167
}
139
168
pub fn try_encode ( & self ) -> Result < WebPMemory , AnimEncodeError > {
140
- unsafe { anim_encode ( & self ) }
169
+ let encoder = self . encoder ;
170
+ unsafe {
171
+ WebPAnimEncoderAdd ( encoder, std:: ptr:: null_mut ( ) , 0 , std:: ptr:: null ( ) ) ;
172
+
173
+ let mut webp_data = std:: mem:: MaybeUninit :: < WebPData > :: uninit ( ) ;
174
+ let ok = WebPAnimEncoderAssemble ( encoder, webp_data. as_mut_ptr ( ) ) ;
175
+ if ok == 0 {
176
+ //ok == false
177
+ let cstring = WebPAnimEncoderGetError ( encoder) ;
178
+ let cstring = CString :: from_raw ( cstring as * mut _ ) ;
179
+ let string = cstring. to_string_lossy ( ) . to_string ( ) ;
180
+ return Err ( AnimEncodeError :: WebPAnimEncoderGetError ( string) ) ;
181
+ }
182
+ let mux = WebPMuxCreateInternal ( webp_data. as_ptr ( ) , 1 , self . mux_abi_version ) ;
183
+ let mux_error = WebPMuxSetAnimationParams ( mux, & self . muxparams ) ;
184
+ if mux_error != WebPMuxError :: WEBP_MUX_OK {
185
+ return Err ( AnimEncodeError :: WebPMuxError ( mux_error) ) ;
186
+ }
187
+ let mut raw_data: WebPData = webp_data. assume_init ( ) ;
188
+ WebPDataClear ( & mut raw_data) ;
189
+ let mut webp_data = std:: mem:: MaybeUninit :: < WebPData > :: uninit ( ) ;
190
+ WebPMuxAssemble ( mux, webp_data. as_mut_ptr ( ) ) ;
191
+ WebPMuxDelete ( mux) ;
192
+ let raw_data: WebPData = webp_data. assume_init ( ) ;
193
+ Ok ( WebPMemory ( raw_data. bytes as * mut u8 , raw_data. size ) )
194
+ }
195
+ }
196
+ }
197
+
198
+ impl Drop for AnimEncoder < ' _ > {
199
+ fn drop ( & mut self ) {
200
+ unsafe { WebPAnimEncoderDelete ( self . encoder ) } ;
141
201
}
142
202
}
143
203
@@ -147,59 +207,3 @@ pub enum AnimEncodeError {
147
207
WebPMuxError ( WebPMuxError ) ,
148
208
WebPAnimEncoderGetError ( String ) ,
149
209
}
150
- unsafe fn anim_encode ( all_frame : & AnimEncoder ) -> Result < WebPMemory , AnimEncodeError > {
151
- let width = all_frame. width ;
152
- let height = all_frame. height ;
153
- let mut uninit = std:: mem:: MaybeUninit :: < WebPAnimEncoderOptions > :: uninit ( ) ;
154
-
155
- let mux_abi_version = WebPGetMuxABIVersion ( ) ;
156
- WebPAnimEncoderOptionsInitInternal ( uninit. as_mut_ptr ( ) , mux_abi_version) ;
157
- let encoder = WebPAnimEncoderNewInternal (
158
- width as i32 ,
159
- height as i32 ,
160
- uninit. as_ptr ( ) ,
161
- mux_abi_version,
162
- ) ;
163
- let mut frame_pictures = vec ! [ ] ;
164
- for frame in all_frame. frames . iter ( ) {
165
- let mut pic = crate :: new_picture ( frame. image , frame. layout , width, height) ;
166
- let config = frame. config . unwrap_or ( all_frame. config ) ;
167
- let ok = WebPAnimEncoderAdd (
168
- encoder,
169
- & mut * pic as * mut _ ,
170
- frame. timestamp as std:: os:: raw:: c_int ,
171
- config,
172
- ) ;
173
- if ok == 0 {
174
- //ok == false
175
- WebPAnimEncoderDelete ( encoder) ;
176
- return Err ( AnimEncodeError :: WebPEncodingError ( pic. error_code ) ) ;
177
- }
178
- frame_pictures. push ( pic) ;
179
- }
180
- WebPAnimEncoderAdd ( encoder, std:: ptr:: null_mut ( ) , 0 , std:: ptr:: null ( ) ) ;
181
-
182
- let mut webp_data = std:: mem:: MaybeUninit :: < WebPData > :: uninit ( ) ;
183
- let ok = WebPAnimEncoderAssemble ( encoder, webp_data. as_mut_ptr ( ) ) ;
184
- if ok == 0 {
185
- //ok == false
186
- let cstring = WebPAnimEncoderGetError ( encoder) ;
187
- let cstring = CString :: from_raw ( cstring as * mut _ ) ;
188
- let string = cstring. to_string_lossy ( ) . to_string ( ) ;
189
- WebPAnimEncoderDelete ( encoder) ;
190
- return Err ( AnimEncodeError :: WebPAnimEncoderGetError ( string) ) ;
191
- }
192
- WebPAnimEncoderDelete ( encoder) ;
193
- let mux = WebPMuxCreateInternal ( webp_data. as_ptr ( ) , 1 , mux_abi_version) ;
194
- let mux_error = WebPMuxSetAnimationParams ( mux, & all_frame. muxparams ) ;
195
- if mux_error != WebPMuxError :: WEBP_MUX_OK {
196
- return Err ( AnimEncodeError :: WebPMuxError ( mux_error) ) ;
197
- }
198
- let mut raw_data: WebPData = webp_data. assume_init ( ) ;
199
- WebPDataClear ( & mut raw_data) ;
200
- let mut webp_data = std:: mem:: MaybeUninit :: < WebPData > :: uninit ( ) ;
201
- WebPMuxAssemble ( mux, webp_data. as_mut_ptr ( ) ) ;
202
- WebPMuxDelete ( mux) ;
203
- let raw_data: WebPData = webp_data. assume_init ( ) ;
204
- Ok ( WebPMemory ( raw_data. bytes as * mut u8 , raw_data. size ) )
205
- }
0 commit comments