@@ -188,6 +188,14 @@ class AbstractMovieWriter(abc.ABC):
188
188
``writer`` argument of `Animation.save()`.
189
189
'''
190
190
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
+
191
199
@abc .abstractmethod
192
200
def setup (self , fig , outfile , dpi = None ):
193
201
'''
@@ -203,6 +211,17 @@ def setup(self, fig, outfile, dpi=None):
203
211
The DPI (or resolution) for the file. This controls the size
204
212
in pixels of the resulting movie file. Default is ``fig.dpi``.
205
213
'''
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 )
206
225
207
226
@abc .abstractmethod
208
227
def grab_frame (self , ** savefig_kwargs ):
@@ -275,7 +294,7 @@ def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
275
294
output file. Some keys that may be of use include:
276
295
title, artist, genre, subject, copyright, srcform, comment.
277
296
"""
278
- if self . __class__ is MovieWriter :
297
+ if type ( self ) is MovieWriter :
279
298
# TODO MovieWriter is still an abstract class and needs to be
280
299
# extended with a mixin. This should be clearer in naming
281
300
# 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,
284
303
'MovieWriter cannot be instantiated directly. Please use one '
285
304
'of its subclasses.' )
286
305
287
- self .fps = fps
288
- self .frame_format = 'rgba'
306
+ super ().__init__ (fps = fps , metadata = metadata )
289
307
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'
299
309
300
310
if extra_args is None :
301
311
self .extra_args = list (mpl .rcParams [self .args_key ])
302
312
else :
303
313
self .extra_args = extra_args
304
314
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
-
316
315
def _adjust_frame_size (self ):
317
316
if self .codec == 'h264' :
318
317
wo , ho = self .fig .get_size_inches ()
@@ -340,13 +339,8 @@ def setup(self, fig, outfile, dpi=None):
340
339
The DPI (or resolution) for the file. This controls the size
341
340
in pixels of the resulting movie file. Default is fig.dpi.
342
341
'''
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 )
348
343
self ._w , self ._h = self ._adjust_frame_size ()
349
-
350
344
# Run here so that grab_frame() can write the data to a pipe. This
351
345
# eliminates the need for temp files.
352
346
self ._run ()
@@ -540,35 +534,27 @@ def cleanup(self):
540
534
541
535
542
536
@writers .register ('pillow' )
543
- class PillowWriter (MovieWriter ):
537
+ class PillowWriter (AbstractMovieWriter ):
544
538
@classmethod
545
539
def isAvailable (cls ):
546
540
return True
547
541
548
- def __init__ (self , * args , ** kwargs ):
549
- if kwargs .get ("extra_args" ) is None :
550
- kwargs ["extra_args" ] = ()
551
- super ().__init__ (* args , ** kwargs )
552
-
553
542
def setup (self , fig , outfile , dpi = None ):
543
+ super ().setup (fig , outfile , dpi = dpi )
554
544
self ._frames = []
555
- self ._outfile = outfile
556
- self ._dpi = dpi
557
- self ._fig = fig
558
545
559
546
def grab_frame (self , ** savefig_kwargs ):
560
547
from PIL import Image
561
548
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 ()
564
552
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 ))
568
554
569
555
def finish (self ):
570
556
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 :],
572
558
duration = int (1000 / self .fps ), loop = 0 )
573
559
574
560
@@ -1075,11 +1061,15 @@ def func(current_frame: int, total_frames: int) -> Any
1075
1061
if dpi == 'figure' :
1076
1062
dpi = self ._fig .dpi
1077
1063
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
1083
1073
1084
1074
all_anim = [self ]
1085
1075
if extra_anim is not None :
@@ -1091,9 +1081,7 @@ def func(current_frame: int, total_frames: int) -> Any
1091
1081
# registered class.
1092
1082
if isinstance (writer , str ):
1093
1083
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 )
1097
1085
else :
1098
1086
alt_writer = next (writers , None )
1099
1087
if alt_writer is None :
@@ -1102,9 +1090,7 @@ def func(current_frame: int, total_frames: int) -> Any
1102
1090
"save animations." )
1103
1091
_log .warning ("MovieWriter %s unavailable; trying to use %s "
1104
1092
"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 )
1108
1094
_log .info ('Animation.save using %s' , type (writer ))
1109
1095
1110
1096
if 'bbox_inches' in savefig_kwargs :
0 commit comments