@@ -101,19 +101,34 @@ impl Into<DynamicImage> for &AnimFrame<'_> {
101101 }
102102}
103103pub struct AnimEncoder < ' a > {
104- frames : Vec < AnimFrame < ' a > > ,
105104 width : u32 ,
106105 height : u32 ,
107106 config : & ' a WebPConfig ,
107+ mux_abi_version : i32 ,
108108 muxparams : WebPMuxAnimParams ,
109+ encoder : * mut WebPAnimEncoder ,
109110}
110111impl < ' a > AnimEncoder < ' a > {
111112 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+
112126 Self {
113- frames : vec ! [ ] ,
114127 width,
115128 height,
116129 config,
130+ encoder,
131+ mux_abi_version,
117132 muxparams : WebPMuxAnimParams {
118133 bgcolor : 0 ,
119134 loop_count : 0 ,
@@ -130,14 +145,59 @@ impl<'a> AnimEncoder<'a> {
130145 pub fn set_loop_count ( & mut self , loop_count : i32 ) {
131146 self . muxparams . loop_count = loop_count;
132147 }
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 ( ( ) )
135164 }
136165 pub fn encode ( & self ) -> WebPMemory {
137166 self . try_encode ( ) . unwrap ( )
138167 }
139168 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 ) } ;
141201 }
142202}
143203
@@ -147,59 +207,3 @@ pub enum AnimEncodeError {
147207 WebPMuxError ( WebPMuxError ) ,
148208 WebPAnimEncoderGetError ( String ) ,
149209}
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