34
34
from six .moves import xrange
35
35
36
36
import os
37
+ import sys
37
38
import warnings
38
39
import time
39
40
import io
56
57
from matplotlib .path import Path
57
58
from matplotlib .cbook import mplDeprecation
58
59
60
+ try :
61
+ from importlib import import_module
62
+ except :
63
+ # simple python 2.6 implementation (no relative imports)
64
+ def import_module (name ):
65
+ __import__ (name )
66
+ return sys .modules [name ]
67
+
59
68
try :
60
69
from PIL import Image
61
70
_has_pil = True
62
71
except ImportError :
63
72
_has_pil = False
64
73
65
- _backend_d = {}
74
+
75
+ _default_filetypes = {
76
+ 'ps' : 'Postscript' ,
77
+ 'eps' : 'Encapsulated Postscript' ,
78
+ 'pdf' : 'Portable Document Format' ,
79
+ 'pgf' : 'PGF code for LaTeX' ,
80
+ 'png' : 'Portable Network Graphics' ,
81
+ 'raw' : 'Raw RGBA bitmap' ,
82
+ 'rgba' : 'Raw RGBA bitmap' ,
83
+ 'svg' : 'Scalable Vector Graphics' ,
84
+ 'svgz' : 'Scalable Vector Graphics'
85
+ }
86
+
87
+
88
+ _default_backends = {
89
+ 'ps' : 'matplotlib.backends.backend_ps' ,
90
+ 'eps' : 'matplotlib.backends.backend_ps' ,
91
+ 'pdf' : 'matplotlib.backends.backend_pdf' ,
92
+ 'pgf' : 'matplotlib.backends.backend_pgf' ,
93
+ 'png' : 'matplotlib.backends.backend_agg' ,
94
+ 'raw' : 'matplotlib.backends.backend_agg' ,
95
+ 'rgba' : 'matplotlib.backends.backend_agg' ,
96
+ 'svg' : 'matplotlib.backends.backend_svg' ,
97
+ 'svgz' : 'matplotlib.backends.backend_svg' ,
98
+ }
99
+
100
+
101
+ def register_backend (format , backend , description ):
102
+ """
103
+ Register a backend for saving to a given file format.
104
+
105
+ *format*
106
+ File extention
107
+
108
+ *backend*
109
+ Backend for handling file output (module string or canvas class)
110
+
111
+ *description*
112
+ Description of the file type
113
+ """
114
+ _default_backends [format ] = backend
115
+ _default_filetypes [format ] = description
66
116
67
117
68
- def register_backend (format , backend_class ):
69
- _backend_d [format ] = backend_class
118
+ def get_registered_canvas_class (format ):
119
+ """
120
+ Return the registered default canvas for given file format.
121
+ Handles deferred import of required backend.
122
+ """
123
+ if format not in _default_backends :
124
+ return None
125
+ backend_class = _default_backends [format ]
126
+ if cbook .is_string_like (backend_class ):
127
+ backend_class = import_module (backend_class ).FigureCanvas
128
+ _default_backends [format ] = backend_class
129
+ return backend_class
70
130
71
131
72
132
class ShowBase (object ):
@@ -1566,6 +1626,20 @@ class FigureCanvasBase(object):
1566
1626
1567
1627
supports_blit = True
1568
1628
1629
+ filetypes = _default_filetypes
1630
+ if _has_pil :
1631
+ # JPEG support
1632
+ register_backend ('jpg' , 'matplotlib.backends.backend_agg' ,
1633
+ 'Joint Photographic Experts Group' )
1634
+ register_backend ('jpeg' , 'matplotlib.backends.backend_agg' ,
1635
+ 'Joint Photographic Experts Group' )
1636
+
1637
+ # TIFF support
1638
+ register_backend ('tif' , 'matplotlib.backends.backend_agg' ,
1639
+ 'Tagged Image File Format' )
1640
+ register_backend ('tiff' , 'matplotlib.backends.backend_agg' ,
1641
+ 'Tagged Image File Format' )
1642
+
1569
1643
def __init__ (self , figure ):
1570
1644
figure .set_canvas (self )
1571
1645
self .figure = figure
@@ -1927,119 +2001,6 @@ def get_width_height(self):
1927
2001
"""
1928
2002
return int (self .figure .bbox .width ), int (self .figure .bbox .height )
1929
2003
1930
- filetypes = {
1931
- 'eps' : 'Encapsulated Postscript' ,
1932
- 'pdf' : 'Portable Document Format' ,
1933
- 'pgf' : 'LaTeX PGF Figure' ,
1934
- 'png' : 'Portable Network Graphics' ,
1935
- 'ps' : 'Postscript' ,
1936
- 'raw' : 'Raw RGBA bitmap' ,
1937
- 'rgba' : 'Raw RGBA bitmap' ,
1938
- 'svg' : 'Scalable Vector Graphics' ,
1939
- 'svgz' : 'Scalable Vector Graphics' }
1940
-
1941
- # All of these print_* functions do a lazy import because
1942
- # a) otherwise we'd have cyclical imports, since all of these
1943
- # classes inherit from FigureCanvasBase
1944
- # b) so we don't import a bunch of stuff the user may never use
1945
-
1946
- # TODO: these print_* throw ImportErrror when called from
1947
- # compare_images_decorator (decorators.py line 112)
1948
- # if the backend has not already been loaded earlier on. Simple trigger:
1949
- # >>> import matplotlib.tests.test_spines
1950
- # >>> list(matplotlib.tests.test_spines.test_spines_axes_positions())[0][0]()
1951
-
1952
- def print_eps (self , * args , ** kwargs ):
1953
- from .backends .backend_ps import FigureCanvasPS # lazy import
1954
- ps = self .switch_backends (FigureCanvasPS )
1955
- return ps .print_eps (* args , ** kwargs )
1956
-
1957
- def print_pdf (self , * args , ** kwargs ):
1958
- from .backends .backend_pdf import FigureCanvasPdf # lazy import
1959
- pdf = self .switch_backends (FigureCanvasPdf )
1960
- return pdf .print_pdf (* args , ** kwargs )
1961
-
1962
- def print_pgf (self , * args , ** kwargs ):
1963
- from .backends .backend_pgf import FigureCanvasPgf # lazy import
1964
- pgf = self .switch_backends (FigureCanvasPgf )
1965
- return pgf .print_pgf (* args , ** kwargs )
1966
-
1967
- def print_png (self , * args , ** kwargs ):
1968
- from .backends .backend_agg import FigureCanvasAgg # lazy import
1969
- agg = self .switch_backends (FigureCanvasAgg )
1970
- return agg .print_png (* args , ** kwargs )
1971
-
1972
- def print_ps (self , * args , ** kwargs ):
1973
- from .backends .backend_ps import FigureCanvasPS # lazy import
1974
- ps = self .switch_backends (FigureCanvasPS )
1975
- return ps .print_ps (* args , ** kwargs )
1976
-
1977
- def print_raw (self , * args , ** kwargs ):
1978
- from .backends .backend_agg import FigureCanvasAgg # lazy import
1979
- agg = self .switch_backends (FigureCanvasAgg )
1980
- return agg .print_raw (* args , ** kwargs )
1981
- print_bmp = print_rgba = print_raw
1982
-
1983
- def print_svg (self , * args , ** kwargs ):
1984
- from .backends .backend_svg import FigureCanvasSVG # lazy import
1985
- svg = self .switch_backends (FigureCanvasSVG )
1986
- return svg .print_svg (* args , ** kwargs )
1987
-
1988
- def print_svgz (self , * args , ** kwargs ):
1989
- from .backends .backend_svg import FigureCanvasSVG # lazy import
1990
- svg = self .switch_backends (FigureCanvasSVG )
1991
- return svg .print_svgz (* args , ** kwargs )
1992
-
1993
- if _has_pil :
1994
- filetypes ['jpg' ] = 'Joint Photographic Experts Group'
1995
- filetypes ['jpeg' ] = filetypes ['jpg' ]
1996
-
1997
- def print_jpg (self , filename_or_obj , * args , ** kwargs ):
1998
- """
1999
- Supported kwargs:
2000
-
2001
- *quality*: The image quality, on a scale from 1 (worst) to
2002
- 95 (best). The default is 95, if not given in the
2003
- matplotlibrc file in the savefig.jpeg_quality parameter.
2004
- Values above 95 should be avoided; 100 completely
2005
- disables the JPEG quantization stage.
2006
-
2007
- *optimize*: If present, indicates that the encoder should
2008
- make an extra pass over the image in order to select
2009
- optimal encoder settings.
2010
-
2011
- *progressive*: If present, indicates that this image
2012
- should be stored as a progressive JPEG file.
2013
- """
2014
- from .backends .backend_agg import FigureCanvasAgg # lazy import
2015
- agg = self .switch_backends (FigureCanvasAgg )
2016
- buf , size = agg .print_to_buffer ()
2017
- if kwargs .pop ("dryrun" , False ):
2018
- return
2019
- image = Image .frombuffer ('RGBA' , size , buf , 'raw' , 'RGBA' , 0 , 1 )
2020
- options = cbook .restrict_dict (kwargs , ['quality' , 'optimize' ,
2021
- 'progressive' ])
2022
-
2023
- if 'quality' not in options :
2024
- options ['quality' ] = rcParams ['savefig.jpeg_quality' ]
2025
-
2026
- return image .save (filename_or_obj , format = 'jpeg' , ** options )
2027
- print_jpeg = print_jpg
2028
-
2029
- filetypes ['tif' ] = filetypes ['tiff' ] = 'Tagged Image File Format'
2030
-
2031
- def print_tif (self , filename_or_obj , * args , ** kwargs ):
2032
- from .backends .backend_agg import FigureCanvasAgg # lazy import
2033
- agg = self .switch_backends (FigureCanvasAgg )
2034
- buf , size = agg .print_to_buffer ()
2035
- if kwargs .pop ("dryrun" , False ):
2036
- return
2037
- image = Image .frombuffer ('RGBA' , size , buf , 'raw' , 'RGBA' , 0 , 1 )
2038
- dpi = (self .figure .dpi , self .figure .dpi )
2039
- return image .save (filename_or_obj , format = 'tiff' ,
2040
- dpi = dpi )
2041
- print_tiff = print_tif
2042
-
2043
2004
@classmethod
2044
2005
def get_supported_filetypes (cls ):
2045
2006
"""Return dict of savefig file formats supported by this backend"""
@@ -2057,29 +2018,27 @@ def get_supported_filetypes_grouped(cls):
2057
2018
groupings [name ].sort ()
2058
2019
return groupings
2059
2020
2060
- def _get_print_method (self , format ):
2021
+ def _get_output_canvas (self , format ):
2022
+ """Return a canvas that is suitable for saving figures to a specified
2023
+ file format. If necessary, this function will switch to a registered
2024
+ backend that supports the format.
2025
+ """
2061
2026
method_name = 'print_%s' % format
2062
2027
2063
- # check for registered backends
2064
- if format in _backend_d :
2065
- backend_class = _backend_d [format ]
2066
-
2067
- def _print_method (* args , ** kwargs ):
2068
- backend = self .switch_backends (backend_class )
2069
- print_method = getattr (backend , method_name )
2070
- return print_method (* args , ** kwargs )
2071
-
2072
- return _print_method
2028
+ # check if this canvas supports the requested format
2029
+ if hasattr (self , method_name ):
2030
+ return self
2073
2031
2074
- formats = self .get_supported_filetypes ()
2075
- if (format not in formats or not hasattr (self , method_name )):
2076
- formats = sorted (formats )
2077
- raise ValueError (
2078
- 'Format "%s" is not supported.\n '
2079
- 'Supported formats: '
2080
- '%s.' % (format , ', ' .join (formats )))
2032
+ # check if there is a default canvas for the requested format
2033
+ canvas_class = get_registered_canvas_class (format )
2034
+ if canvas_class :
2035
+ return self .switch_backends (canvas_class )
2081
2036
2082
- return getattr (self , method_name )
2037
+ # else report error for unsupported format
2038
+ formats = sorted (self .get_supported_filetypes ())
2039
+ raise ValueError ('Format "%s" is not supported.\n '
2040
+ 'Supported formats: '
2041
+ '%s.' % (format , ', ' .join (formats )))
2083
2042
2084
2043
def print_figure (self , filename , dpi = None , facecolor = 'w' , edgecolor = 'w' ,
2085
2044
orientation = 'portrait' , format = None , ** kwargs ):
@@ -2136,7 +2095,9 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
2136
2095
filename = filename .rstrip ('.' ) + '.' + format
2137
2096
format = format .lower ()
2138
2097
2139
- print_method = self ._get_print_method (format )
2098
+ # get canvas object and print method for format
2099
+ canvas = self ._get_output_canvas (format )
2100
+ print_method = getattr (canvas , 'print_%s' % format )
2140
2101
2141
2102
if dpi is None :
2142
2103
dpi = rcParams ['savefig.dpi' ]
0 commit comments