Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe24fc9

Browse files
committed
Merge pull request#2588 from pwuertz/print_refactor
Refactor mechanism for saving files.
2 parents0b1820d +522fbe7 commitbe24fc9

23 files changed

+214
-157
lines changed

‎lib/matplotlib/backend_bases.py

Lines changed: 97 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
fromsix.movesimportxrange
3535

3636
importos
37+
importsys
3738
importwarnings
3839
importtime
3940
importio
@@ -56,17 +57,76 @@
5657
frommatplotlib.pathimportPath
5758
frommatplotlib.cbookimportmplDeprecation
5859

60+
try:
61+
fromimportlibimportimport_module
62+
except:
63+
# simple python 2.6 implementation (no relative imports)
64+
defimport_module(name):
65+
__import__(name)
66+
returnsys.modules[name]
67+
5968
try:
6069
fromPILimportImage
6170
_has_pil=True
6271
exceptImportError:
6372
_has_pil=False
6473

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+
defregister_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
66116

67117

68-
defregister_backend(format,backend_class):
69-
_backend_d[format]=backend_class
118+
defget_registered_canvas_class(format):
119+
"""
120+
Return the registered default canvas for given file format.
121+
Handles deferred import of required backend.
122+
"""
123+
ifformatnotin_default_backends:
124+
returnNone
125+
backend_class=_default_backends[format]
126+
ifcbook.is_string_like(backend_class):
127+
backend_class=import_module(backend_class).FigureCanvas
128+
_default_backends[format]=backend_class
129+
returnbackend_class
70130

71131

72132
classShowBase(object):
@@ -1566,6 +1626,20 @@ class FigureCanvasBase(object):
15661626

15671627
supports_blit=True
15681628

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+
15691643
def__init__(self,figure):
15701644
figure.set_canvas(self)
15711645
self.figure=figure
@@ -1927,119 +2001,6 @@ def get_width_height(self):
19272001
"""
19282002
returnint(self.figure.bbox.width),int(self.figure.bbox.height)
19292003

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-
defprint_eps(self,*args,**kwargs):
1953-
from .backends.backend_psimportFigureCanvasPS# lazy import
1954-
ps=self.switch_backends(FigureCanvasPS)
1955-
returnps.print_eps(*args,**kwargs)
1956-
1957-
defprint_pdf(self,*args,**kwargs):
1958-
from .backends.backend_pdfimportFigureCanvasPdf# lazy import
1959-
pdf=self.switch_backends(FigureCanvasPdf)
1960-
returnpdf.print_pdf(*args,**kwargs)
1961-
1962-
defprint_pgf(self,*args,**kwargs):
1963-
from .backends.backend_pgfimportFigureCanvasPgf# lazy import
1964-
pgf=self.switch_backends(FigureCanvasPgf)
1965-
returnpgf.print_pgf(*args,**kwargs)
1966-
1967-
defprint_png(self,*args,**kwargs):
1968-
from .backends.backend_aggimportFigureCanvasAgg# lazy import
1969-
agg=self.switch_backends(FigureCanvasAgg)
1970-
returnagg.print_png(*args,**kwargs)
1971-
1972-
defprint_ps(self,*args,**kwargs):
1973-
from .backends.backend_psimportFigureCanvasPS# lazy import
1974-
ps=self.switch_backends(FigureCanvasPS)
1975-
returnps.print_ps(*args,**kwargs)
1976-
1977-
defprint_raw(self,*args,**kwargs):
1978-
from .backends.backend_aggimportFigureCanvasAgg# lazy import
1979-
agg=self.switch_backends(FigureCanvasAgg)
1980-
returnagg.print_raw(*args,**kwargs)
1981-
print_bmp=print_rgba=print_raw
1982-
1983-
defprint_svg(self,*args,**kwargs):
1984-
from .backends.backend_svgimportFigureCanvasSVG# lazy import
1985-
svg=self.switch_backends(FigureCanvasSVG)
1986-
returnsvg.print_svg(*args,**kwargs)
1987-
1988-
defprint_svgz(self,*args,**kwargs):
1989-
from .backends.backend_svgimportFigureCanvasSVG# lazy import
1990-
svg=self.switch_backends(FigureCanvasSVG)
1991-
returnsvg.print_svgz(*args,**kwargs)
1992-
1993-
if_has_pil:
1994-
filetypes['jpg']='Joint Photographic Experts Group'
1995-
filetypes['jpeg']=filetypes['jpg']
1996-
1997-
defprint_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_aggimportFigureCanvasAgg# lazy import
2015-
agg=self.switch_backends(FigureCanvasAgg)
2016-
buf,size=agg.print_to_buffer()
2017-
ifkwargs.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'notinoptions:
2024-
options['quality']=rcParams['savefig.jpeg_quality']
2025-
2026-
returnimage.save(filename_or_obj,format='jpeg',**options)
2027-
print_jpeg=print_jpg
2028-
2029-
filetypes['tif']=filetypes['tiff']='Tagged Image File Format'
2030-
2031-
defprint_tif(self,filename_or_obj,*args,**kwargs):
2032-
from .backends.backend_aggimportFigureCanvasAgg# lazy import
2033-
agg=self.switch_backends(FigureCanvasAgg)
2034-
buf,size=agg.print_to_buffer()
2035-
ifkwargs.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-
returnimage.save(filename_or_obj,format='tiff',
2040-
dpi=dpi)
2041-
print_tiff=print_tif
2042-
20432004
@classmethod
20442005
defget_supported_filetypes(cls):
20452006
"""Return dict of savefig file formats supported by this backend"""
@@ -2057,29 +2018,27 @@ def get_supported_filetypes_grouped(cls):
20572018
groupings[name].sort()
20582019
returngroupings
20592020

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+
"""
20612026
method_name='print_%s'%format
20622027

2063-
# check for registered backends
2064-
ifformatin_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-
returnprint_method(*args,**kwargs)
2071-
2072-
return_print_method
2028+
# check if this canvas supports the requested format
2029+
ifhasattr(self,method_name):
2030+
returnself
20732031

2074-
formats=self.get_supported_filetypes()
2075-
if (formatnotinformatsornothasattr(self,method_name)):
2076-
formats=sorted(formats)
2077-
raiseValueError(
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+
ifcanvas_class:
2035+
returnself.switch_backends(canvas_class)
20812036

2082-
returngetattr(self,method_name)
2037+
# else report error for unsupported format
2038+
formats=sorted(self.get_supported_filetypes())
2039+
raiseValueError('Format "%s" is not supported.\n'
2040+
'Supported formats: '
2041+
'%s.'% (format,', '.join(formats)))
20832042

20842043
defprint_figure(self,filename,dpi=None,facecolor='w',edgecolor='w',
20852044
orientation='portrait',format=None,**kwargs):
@@ -2136,7 +2095,9 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
21362095
filename=filename.rstrip('.')+'.'+format
21372096
format=format.lower()
21382097

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)
21402101

21412102
ifdpiisNone:
21422103
dpi=rcParams['savefig.dpi']

‎lib/matplotlib/backends/backend_agg.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* linewidth
99
* lines, rectangles, ellipses
1010
* clipping to a rectangle
11-
* output to RGBA and PNG
11+
* output to RGBA and PNG, optionally JPEG and TIFF
1212
* alpha blending
1313
* DPI scaling properly - everything scales properly (dashes, linewidths, etc)
1414
* draw polygon
@@ -30,7 +30,7 @@
3030
frommatplotlibimportverbose,rcParams
3131
frommatplotlib.backend_basesimportRendererBase,\
3232
FigureManagerBase,FigureCanvasBase
33-
frommatplotlib.cbookimportis_string_like,maxdict
33+
frommatplotlib.cbookimportis_string_like,maxdict,restrict_dict
3434
frommatplotlib.figureimportFigure
3535
frommatplotlib.font_managerimportfindfont
3636
frommatplotlib.ft2fontimportFT2Font,LOAD_FORCE_AUTOHINT,LOAD_NO_HINTING, \
@@ -42,6 +42,12 @@
4242
frommatplotlib.backends._backend_aggimportRendererAggas_RendererAgg
4343
frommatplotlibimport_png
4444

45+
try:
46+
fromPILimportImage
47+
_has_pil=True
48+
exceptImportError:
49+
_has_pil=False
50+
4551
backend_version='v2.2'
4652

4753
defget_hinting_flag():
@@ -456,8 +462,6 @@ def draw(self):
456462
finally:
457463
RendererAgg.lock.release()
458464

459-
460-
461465
defget_renderer(self,cleared=False):
462466
l,b,w,h=self.figure.bbox.bounds
463467
key=w,h,self.figure.dpi
@@ -533,3 +537,50 @@ def print_to_buffer(self):
533537
(int(renderer.width),int(renderer.height)))
534538
renderer.dpi=original_dpi
535539
returnresult
540+
541+
if_has_pil:
542+
543+
# add JPEG support
544+
defprint_jpg(self,filename_or_obj,*args,**kwargs):
545+
"""
546+
Supported kwargs:
547+
548+
*quality*: The image quality, on a scale from 1 (worst) to
549+
95 (best). The default is 95, if not given in the
550+
matplotlibrc file in the savefig.jpeg_quality parameter.
551+
Values above 95 should be avoided; 100 completely
552+
disables the JPEG quantization stage.
553+
554+
*optimize*: If present, indicates that the encoder should
555+
make an extra pass over the image in order to select
556+
optimal encoder settings.
557+
558+
*progressive*: If present, indicates that this image
559+
should be stored as a progressive JPEG file.
560+
"""
561+
buf,size=self.print_to_buffer()
562+
ifkwargs.pop("dryrun",False):
563+
return
564+
image=Image.frombuffer('RGBA',size,buf,'raw','RGBA',0,1)
565+
options=restrict_dict(kwargs, ['quality','optimize',
566+
'progressive'])
567+
568+
if'quality'notinoptions:
569+
options['quality']=rcParams['savefig.jpeg_quality']
570+
571+
returnimage.save(filename_or_obj,format='jpeg',**options)
572+
print_jpeg=print_jpg
573+
574+
# add TIFF support
575+
defprint_tif(self,filename_or_obj,*args,**kwargs):
576+
buf,size=self.print_to_buffer()
577+
ifkwargs.pop("dryrun",False):
578+
return
579+
image=Image.frombuffer('RGBA',size,buf,'raw','RGBA',0,1)
580+
dpi= (self.figure.dpi,self.figure.dpi)
581+
returnimage.save(filename_or_obj,format='tiff',
582+
dpi=dpi)
583+
print_tiff=print_tif
584+
585+
586+
FigureCanvas=FigureCanvasAgg

‎lib/matplotlib/backends/backend_cairo.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,3 +514,6 @@ def _save (self, fo, format, **kwargs):
514514

515515
ctx.show_page()
516516
surface.finish()
517+
518+
519+
FigureCanvas=FigureCanvasCairo

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp