@@ -188,6 +188,14 @@ class AbstractMovieWriter(abc.ABC):
188188 ``writer`` argument of `Animation.save()`.
189189 '''
190190
191+ def __init__ (self , fps = 5 , metadata = None , codec = None , bitrate = None ):
192+ self .fps = fps
193+ self .metadata = metadata if metadata is not None else {}
194+ self .codec = (
195+ mpl .rcParams ['animation.codec' ] if codec is None else codec )
196+ self .bitrate = (
197+ mpl .rcParams ['animation.bitrate' ] if bitrate is None else bitrate )
198+
191199 @abc .abstractmethod
192200 def setup (self , fig , outfile , dpi = None ):
193201 '''
@@ -203,6 +211,17 @@ def setup(self, fig, outfile, dpi=None):
203211 The DPI (or resolution) for the file. This controls the size
204212 in pixels of the resulting movie file. Default is ``fig.dpi``.
205213 '''
214+ self .outfile = outfile
215+ self .fig = fig
216+ if dpi is None :
217+ dpi = self .fig .dpi
218+ self .dpi = dpi
219+
220+ @property
221+ def frame_size (self ):
222+ '''A tuple ``(width, height)`` in pixels of a movie frame.'''
223+ w , h = self .fig .get_size_inches ()
224+ return int (w * self .dpi ), int (h * self .dpi )
206225
207226 @abc .abstractmethod
208227 def grab_frame (self , ** savefig_kwargs ):
@@ -275,7 +294,7 @@ def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
275294 output file. Some keys that may be of use include:
276295 title, artist, genre, subject, copyright, srcform, comment.
277296 """
278- if self . __class__ is MovieWriter :
297+ if type ( self ) is MovieWriter :
279298 # TODO MovieWriter is still an abstract class and needs to be
280299 # extended with a mixin. This should be clearer in naming
281300 # and description. For now, just give a reasonable error
@@ -284,35 +303,15 @@ def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
284303 'MovieWriter cannot be instantiated directly. Please use one '
285304 'of its subclasses.' )
286305
287- self .fps = fps
288- self .frame_format = 'rgba'
306+ super ().__init__ (fps = fps , metadata = metadata )
289307
290- if codec is None :
291- self .codec = mpl .rcParams ['animation.codec' ]
292- else :
293- self .codec = codec
294-
295- if bitrate is None :
296- self .bitrate = mpl .rcParams ['animation.bitrate' ]
297- else :
298- self .bitrate = bitrate
308+ self .frame_format = 'rgba'
299309
300310 if extra_args is None :
301311 self .extra_args = list (mpl .rcParams [self .args_key ])
302312 else :
303313 self .extra_args = extra_args
304314
305- if metadata is None :
306- self .metadata = dict ()
307- else :
308- self .metadata = metadata
309-
310- @property
311- def frame_size (self ):
312- '''A tuple ``(width, height)`` in pixels of a movie frame.'''
313- w , h = self .fig .get_size_inches ()
314- return int (w * self .dpi ), int (h * self .dpi )
315-
316315 def _adjust_frame_size (self ):
317316 if self .codec == 'h264' :
318317 wo , ho = self .fig .get_size_inches ()
@@ -340,13 +339,8 @@ def setup(self, fig, outfile, dpi=None):
340339 The DPI (or resolution) for the file. This controls the size
341340 in pixels of the resulting movie file. Default is fig.dpi.
342341 '''
343- self .outfile = outfile
344- self .fig = fig
345- if dpi is None :
346- dpi = self .fig .dpi
347- self .dpi = dpi
342+ super ().setup (fig , outfile , dpi = dpi )
348343 self ._w , self ._h = self ._adjust_frame_size ()
349-
350344 # Run here so that grab_frame() can write the data to a pipe. This
351345 # eliminates the need for temp files.
352346 self ._run ()
@@ -540,35 +534,27 @@ def cleanup(self):
540534
541535
542536@writers .register ('pillow' )
543- class PillowWriter (MovieWriter ):
537+ class PillowWriter (AbstractMovieWriter ):
544538 @classmethod
545539 def isAvailable (cls ):
546540 return True
547541
548- def __init__ (self , * args , ** kwargs ):
549- if kwargs .get ("extra_args" ) is None :
550- kwargs ["extra_args" ] = ()
551- super ().__init__ (* args , ** kwargs )
552-
553542 def setup (self , fig , outfile , dpi = None ):
543+ super ().setup (fig , outfile , dpi = dpi )
554544 self ._frames = []
555- self ._outfile = outfile
556- self ._dpi = dpi
557- self ._fig = fig
558545
559546 def grab_frame (self , ** savefig_kwargs ):
560547 from PIL import Image
561548 buf = BytesIO ()
562- self ._fig .savefig (buf , ** dict (savefig_kwargs , format = "rgba" ))
563- renderer = self ._fig .canvas .get_renderer ()
549+ self .fig .savefig (
550+ buf , ** {** savefig_kwargs , "format" : "rgba" , "dpi" : self .dpi })
551+ renderer = self .fig .canvas .get_renderer ()
564552 self ._frames .append (Image .frombuffer (
565- "RGBA" ,
566- (int (renderer .width ), int (renderer .height )), buf .getbuffer (),
567- "raw" , "RGBA" , 0 , 1 ))
553+ "RGBA" , self .frame_size , buf .getbuffer (), "raw" , "RGBA" , 0 , 1 ))
568554
569555 def finish (self ):
570556 self ._frames [0 ].save (
571- self ._outfile , save_all = True , append_images = self ._frames [1 :],
557+ self .outfile , save_all = True , append_images = self ._frames [1 :],
572558 duration = int (1000 / self .fps ), loop = 0 )
573559
574560
@@ -1075,11 +1061,15 @@ def func(current_frame: int, total_frames: int) -> Any
10751061 if dpi == 'figure' :
10761062 dpi = self ._fig .dpi
10771063
1078- if codec is None :
1079- codec = mpl .rcParams ['animation.codec' ]
1080-
1081- if bitrate is None :
1082- bitrate = mpl .rcParams ['animation.bitrate' ]
1064+ writer_kwargs = {}
1065+ if codec is not None :
1066+ writer_kwargs ['codec' ] = codec
1067+ if bitrate is not None :
1068+ writer_kwargs ['bitrate' ] = bitrate
1069+ if extra_args is not None :
1070+ writer_kwargs ['extra_args' ] = extra_args
1071+ if metadata is not None :
1072+ writer_kwargs ['metadata' ] = metadata
10831073
10841074 all_anim = [self ]
10851075 if extra_anim is not None :
@@ -1091,9 +1081,7 @@ def func(current_frame: int, total_frames: int) -> Any
10911081 # registered class.
10921082 if isinstance (writer , str ):
10931083 if writers .is_available (writer ):
1094- writer = writers [writer ](fps , codec , bitrate ,
1095- extra_args = extra_args ,
1096- metadata = metadata )
1084+ writer = writers [writer ](fps , ** writer_kwargs )
10971085 else :
10981086 alt_writer = next (writers , None )
10991087 if alt_writer is None :
@@ -1102,9 +1090,7 @@ def func(current_frame: int, total_frames: int) -> Any
11021090 "save animations." )
11031091 _log .warning ("MovieWriter %s unavailable; trying to use %s "
11041092 "instead." , writer , alt_writer )
1105- writer = alt_writer (
1106- fps , codec , bitrate ,
1107- extra_args = extra_args , metadata = metadata )
1093+ writer = alt_writer (fps , ** writer_kwargs )
11081094 _log .info ('Animation.save using %s' , type (writer ))
11091095
11101096 if 'bbox_inches' in savefig_kwargs :
0 commit comments