From 05a9d9e885178023c202bdc5b32466abf74995c1 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Sun, 17 Feb 2013 13:35:09 -0500 Subject: [PATCH 1/9] https://github.com/matplotlib/matplotlib/pull/1710 When a font doesn't have a glyph name, we should synthesize. This fixes the Arial font problems under Windows 8. --- src/ft2font.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ft2font.cpp b/src/ft2font.cpp index 19e18e67914a..3104c4da9215 100644 --- a/src/ft2font.cpp +++ b/src/ft2font.cpp @@ -1616,16 +1616,21 @@ FT2Font::get_glyph_name(const Py::Tuple & args) _VERBOSE("FT2Font::get_glyph_name"); args.verify_length(1); - if (!FT_HAS_GLYPH_NAMES(face)) - { - throw Py::RuntimeError("Face has no glyph names"); - } char buffer[128]; - if (FT_Get_Glyph_Name(face, (FT_UInt) (unsigned long)Py::Int(args[0]), buffer, 128)) - { - throw Py::RuntimeError("Could not get glyph names."); - } + + FT_UInt glyph_number = Py::Int(args[0]); + + if (!FT_HAS_GLYPH_NAMES(face)) + { + snprintf(buffer, 128, "uni%04x", glyph_number); + } else { + if (FT_Get_Glyph_Name(face, glyph_number, buffer, 128)) + { + throw Py::RuntimeError("Could not get glyph names."); + } + } + return Py::String(buffer); } PYCXX_VARARGS_METHOD_DECL(FT2Font, get_glyph_name) From 14be18e0314040fd5e31c622e3c5f3ffb4957f07 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Wed, 20 Feb 2013 19:44:08 -0500 Subject: [PATCH 2/9] Set default quality for rendering jpegs with PIL to 95. --- lib/matplotlib/backend_bases.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 53555ba5caf2..b14a23974534 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1930,7 +1930,7 @@ def print_jpg(self, filename_or_obj, *args, **kwargs): Supported kwargs: *quality*: The image quality, on a scale from 1 (worst) to - 95 (best). The default is 75. Values above 95 should + 95 (best). The default is 95. Values above 95 should be avoided; 100 completely disables the JPEG quantization stage. @@ -1949,6 +1949,9 @@ def print_jpg(self, filename_or_obj, *args, **kwargs): image = Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1) options = cbook.restrict_dict(kwargs, ['quality', 'optimize', 'progressive']) + + if 'quality' not in options: options['quality'] = 95 + return image.save(filename_or_obj, format='jpeg', **options) print_jpeg = print_jpg From 3abd91e874d35756e25d198515b01d0e242d23f5 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Fri, 22 Feb 2013 23:35:38 -0500 Subject: [PATCH 3/9] Straw man commit for making the jpeg quality (when saved by PIL) configurable via rcParams. --- lib/matplotlib/backend_bases.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index b14a23974534..e4840aa02dff 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1930,9 +1930,10 @@ def print_jpg(self, filename_or_obj, *args, **kwargs): Supported kwargs: *quality*: The image quality, on a scale from 1 (worst) to - 95 (best). The default is 95. Values above 95 should - be avoided; 100 completely disables the JPEG - quantization stage. + 95 (best). The default is 95, if not given in the + matplotlibrc file in the savefig.jpeg_quality parameter. + Values above 95 should be avoided; 100 completely + disables the JPEG quantization stage. *optimize*: If present, indicates that the encoder should make an extra pass over the image in order to select @@ -1950,7 +1951,8 @@ def print_jpg(self, filename_or_obj, *args, **kwargs): options = cbook.restrict_dict(kwargs, ['quality', 'optimize', 'progressive']) - if 'quality' not in options: options['quality'] = 95 + if 'quality' not in options: + options['quality'] = rcParams.get('savefig.jpeg_quality',95) return image.save(filename_or_obj, format='jpeg', **options) print_jpeg = print_jpg From e1c237848ff0a0f366da123cda8dbd582df1e042 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Tue, 5 Mar 2013 18:40:39 -0500 Subject: [PATCH 4/9] Added savefig.jpeg_quality to the rcParams correctly With a short one-line doc in matplotlibrc.template. --- lib/matplotlib/backend_bases.py | 2 +- lib/matplotlib/rcsetup.py | 1 + matplotlibrc.template | 17 +++++++++-------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index e4840aa02dff..d2f5b9c942fd 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1952,7 +1952,7 @@ def print_jpg(self, filename_or_obj, *args, **kwargs): 'progressive']) if 'quality' not in options: - options['quality'] = rcParams.get('savefig.jpeg_quality',95) + options['quality'] = rcParams['savefig.jpeg_quality'] return image.save(filename_or_obj, format='jpeg', **options) print_jpeg = print_jpg diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index bea9e7eea098..a26d0f603d7e 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -687,6 +687,7 @@ def __call__(self, s): 'savefig.frameon': [True, validate_bool], 'savefig.orientation': ['portrait', validate_orientation], # edgecolor; #white + 'savefig.jpeg_quality': [95, validate_int], # what to add to extensionless filenames 'savefig.extension': ['png', deprecate_savefig_extension], # value checked by backend at runtime diff --git a/matplotlibrc.template b/matplotlibrc.template index 64f802233b19..a782a3e9f3b6 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -362,14 +362,15 @@ text.hinting_factor : 8 # Specifies the amount of softness for hinting in the # the default savefig params can be different from the display params # e.g., you may want a higher resolution, or to make the figure # background white -#savefig.dpi : 100 # figure dots per inch -#savefig.facecolor : white # figure facecolor when saving -#savefig.edgecolor : white # figure edgecolor when saving -#savefig.format : png # png, ps, pdf, svg -#savefig.bbox : standard # 'tight' or 'standard'. -#savefig.pad_inches : 0.1 # Padding to be used when bbox is set to 'tight' -#savefig.directory : ~ # default directory in savefig dialog box, - # leave empty to always use current working directory +#savefig.dpi : 100 # figure dots per inch +#savefig.facecolor : white # figure facecolor when saving +#savefig.edgecolor : white # figure edgecolor when saving +#savefig.format : png # png, ps, pdf, svg +#savefig.bbox : standard # 'tight' or 'standard'. +#savefig.pad_inches : 0.1 # Padding to be used when bbox is set to 'tight' +#savefig.jpeg_quality: 95 # when a jpeg is saved, the default quality parameter. +#savefig.directory : ~ # default directory in savefig dialog box, + # leave empty to always use current working directory # tk backend params #tk.window_focus : False # Maintain shell focus for TkAgg From 745da0b57df24d03a2fb77b2b81dcedf9e993b5c Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Tue, 5 Mar 2013 19:34:51 -0500 Subject: [PATCH 5/9] added jpeg quality support for gdk backend --- lib/matplotlib/backends/backend_gdk.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_gdk.py b/lib/matplotlib/backends/backend_gdk.py index e66827782d7a..188c2806811b 100644 --- a/lib/matplotlib/backends/backend_gdk.py +++ b/lib/matplotlib/backends/backend_gdk.py @@ -19,6 +19,7 @@ def fn_name(): return sys._getframe(1).f_code.co_name import numpy as np import matplotlib +from matplotlib import rcParams from matplotlib._pylab_helpers import Gcf from matplotlib.backend_bases import RendererBase, GraphicsContextBase, \ FigureManagerBase, FigureCanvasBase @@ -471,4 +472,13 @@ def _print_image(self, filename, format, *args, **kwargs): pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height) - pixbuf.save(filename, format) + # set the default quality, if we are writing a JPEG. + # http://www.pygtk.org/docs/pygtk/class-gdkpixbuf.html#method-gdkpixbuf--save + options = cbook.restrict_dict(kwargs, ['quality']) + if format in ['jpg','jpeg']: + if 'quality' not in options: + options['quality'] = rcParams['savefig.jpeg_quality'] + options['quality'] = str(options['quality']) + + pixbuf.save(filename, format, options=options) + From 05fc06dab4758ce14ff7d32ce297a711b20a2611 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Tue, 5 Mar 2013 19:35:07 -0500 Subject: [PATCH 6/9] Added jpeg quality support for gtk backend --- lib/matplotlib/backends/backend_gtk.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py index 3b30686b86a4..c41114abc747 100644 --- a/lib/matplotlib/backends/backend_gtk.py +++ b/lib/matplotlib/backends/backend_gtk.py @@ -452,7 +452,7 @@ def print_jpeg(self, filename, *args, **kwargs): def print_png(self, filename, *args, **kwargs): return self._print_image(filename, 'png') - def _print_image(self, filename, format): + def _print_image(self, filename, format, *args, **kwargs): if self.flags() & gtk.REALIZED == 0: # for self.window(for pixmap) and has a side effect of altering # figure width,height (via configure-event?) @@ -469,9 +469,18 @@ def _print_image(self, filename, format): pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height) + # set the default quality, if we are writing a JPEG. + # http://www.pygtk.org/docs/pygtk/class-gdkpixbuf.html#method-gdkpixbuf--save + options = cbook.restrict_dict(kwargs, ['quality']) + if format in ['jpg','jpeg']: + if 'quality' not in options: + options['quality'] = rcParams['savefig.jpeg_quality'] + options['quality'] = str(options['quality']) + + if is_string_like(filename): try: - pixbuf.save(filename, format) + pixbuf.save(filename, format, options=options) except gobject.GError as exc: error_msg_gtk('Save figure failure:\n%s' % (exc,), parent=self) elif is_writable_file_like(filename): @@ -479,7 +488,7 @@ def _print_image(self, filename, format): def save_callback(buf, data=None): data.write(buf) try: - pixbuf.save_to_callback(save_callback, format, user_data=filename) + pixbuf.save_to_callback(save_callback, format, user_data=filename, options=options) except gobject.GError as exc: error_msg_gtk('Save figure failure:\n%s' % (exc,), parent=self) else: From 0a3cb52afa04c0c88793c94763488894ada75c14 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Tue, 5 Mar 2013 19:35:42 -0500 Subject: [PATCH 7/9] Added jpeg quality support for wx backend --- lib/matplotlib/backends/backend_wx.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index d4b7e9a5c413..e2991fed928f 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1162,15 +1162,29 @@ def _print_image(self, filename, filetype, *args, **kwargs): gc = renderer.new_gc() self.figure.draw(renderer) + + # image is the object that we call SaveFile on. + image = self.bitmap + + # set the JPEG quality appropriately. Unfortunately, it is only possible + # to set the quality on a wx.Image object. So if we are saving a JPEG, + # convert the wx.Bitmap to a wx.Image, and set the quality. + if filetype == wx.BITMAP_TYPE_JPEG: + jpeg_quality = kwargs.get('quality',rcParams['savefig.jpeg_quality']) + image = self.bitmap.ConvertToImage() + image.SetOption(wx.IMAGE_OPTION_QUALITY,jpeg_quality) + # Now that we have rendered into the bitmap, save it # to the appropriate file type and clean up if is_string_like(filename): - if not self.bitmap.SaveFile(filename, filetype): + if not image.SaveFile(filename, filetype): DEBUG_MSG('print_figure() file save error', 4, self) raise RuntimeError('Could not save figure to %s\n' % (filename)) elif is_writable_file_like(filename): - if not self.bitmap.ConvertToImage().SaveStream(filename, filetype): + if not isinstance(image,wx.Image): + image = image.ConvertToImage() + if not image.SaveStream(filename, filetype): DEBUG_MSG('print_figure() file save error', 4, self) raise RuntimeError('Could not save figure to %s\n' % (filename)) From 56e0c344bcc0b7b5092879859275628f73249b55 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Tue, 5 Mar 2013 20:27:30 -0500 Subject: [PATCH 8/9] bugfix: SetOption for wx.Image takes a string, not an int. --- lib/matplotlib/backends/backend_wx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index e2991fed928f..5288098cb6c7 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1172,7 +1172,7 @@ def _print_image(self, filename, filetype, *args, **kwargs): if filetype == wx.BITMAP_TYPE_JPEG: jpeg_quality = kwargs.get('quality',rcParams['savefig.jpeg_quality']) image = self.bitmap.ConvertToImage() - image.SetOption(wx.IMAGE_OPTION_QUALITY,jpeg_quality) + image.SetOption(wx.IMAGE_OPTION_QUALITY,str(jpeg_quality)) # Now that we have rendered into the bitmap, save it From b81bb3df2d9dc3ceb23cb7716d1f16fa2e35a532 Mon Sep 17 00:00:00 2001 From: Daniel Hyams Date: Fri, 19 Apr 2013 17:47:50 -0400 Subject: [PATCH 9/9] Two newline fixes to comply with PEP8 --- lib/matplotlib/backends/backend_gtk.py | 1 + lib/matplotlib/backends/backend_wx.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py index c41114abc747..b93abdf47a23 100644 --- a/lib/matplotlib/backends/backend_gtk.py +++ b/lib/matplotlib/backends/backend_gtk.py @@ -475,6 +475,7 @@ def _print_image(self, filename, format, *args, **kwargs): if format in ['jpg','jpeg']: if 'quality' not in options: options['quality'] = rcParams['savefig.jpeg_quality'] + options['quality'] = str(options['quality']) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 5288098cb6c7..1a42c533b6a7 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1165,7 +1165,6 @@ def _print_image(self, filename, filetype, *args, **kwargs): # image is the object that we call SaveFile on. image = self.bitmap - # set the JPEG quality appropriately. Unfortunately, it is only possible # to set the quality on a wx.Image object. So if we are saving a JPEG, # convert the wx.Bitmap to a wx.Image, and set the quality.