Hi,I sent this message to the list this time yesterday and it doesn't seem to have either arrived or bounced - so I'm trying again.
I've written a patch (attached) to allow the PS backend to respect the dpi that's given to the FigureCanvasPS on initialisation when saving images. The solution I came with to do this isn't the nicest, but I couldn't see any significantly different way to do it without changing the rendering process for images. What I've done is add a get_image_magnification method to the default backend with a default return value of 1.0. This magnification factor is then taken by the draw method of the figure, axes or image and passed as a keyword argument to the make_image method of the image where it used to scale the widthDisplay and heightDisplay returned from the bounding box. (I also changed the self.make_image(False) call in Image.write_png to self.make_image() as I'm pretty sure that's what was meant to be - and if I hadn't the introduction of my new keyword argument would have resulted in a zero size image.) By returning a magnification of dpi/72.0, the PS backend is able to instruct the image instances to create larger images which it then scales by an appropriate value on output to give the requested dpi. This patch, or something like it, is vital for me at the moment because the low 72 dpi output used by matplotlib at the moment gives rise to some fairly significant distortion to my results. I imagine others will come across the same problem. I hope this patch is useful, Nicholas Young
Index: lib/matplotlib/backend_bases.py =================================================================== --- lib/matplotlib/backend_bases.py (revision 2774) +++ lib/matplotlib/backend_bases.py (working copy) @@ -46,6 +46,14 @@ """ raise NotImplementedError + def get_image_magnification(self): + """ + Get the factor by which to magnify images passed to draw_image. + Allows a backend to have images at a different resolution to other + artists. + """ + return 1.0 + def draw_image(self, x, y, im, bbox): """ Draw the Image instance into the current axes; x is the Index: lib/matplotlib/axes.py =================================================================== --- lib/matplotlib/axes.py (revision 2774) +++ lib/matplotlib/axes.py (working copy) @@ -1021,10 +1021,14 @@ # list of (_image.Image, ox, oy) - ims = [(im.make_image(),0,0) for im in self.images if im.get_visible()] + mag = renderer.get_image_magnification() + ims = [(im.make_image(mag),0,0) + for im in self.images if im.get_visible()] - im = _image.from_images(self.bbox.height(), self.bbox.width(), ims) + im = _image.from_images(self.bbox.height()*mag, + self.bbox.width()*mag, + ims) im.is_grayscale = False l, b, w, h = self.bbox.get_bounds() # composite images need special args so they will not Index: lib/matplotlib/figure.py =================================================================== --- lib/matplotlib/figure.py (revision 2774) +++ lib/matplotlib/figure.py (working copy) @@ -530,8 +530,12 @@ # list of (_image.Image, ox, oy) if not allequal([im.origin for im in self.images]): raise ValueError('Composite images with different origins not supported') - ims = [(im.make_image(), im.ox, im.oy) for im in self.images] - im = _image.from_images(self.bbox.height(), self.bbox.width(), ims) + mag = renderer.get_image_magnification() + ims = [(im.make_image(mag), im.ox*mag, im.oy*mag) + for im in self.images] + im = _image.from_images(self.bbox.height()*mag, + self.bbox.width()*mag, + ims) im.is_grayscale = False l, b, w, h = self.bbox.get_bounds() renderer.draw_image(0, 0, im, self.bbox) Index: lib/matplotlib/image.py =================================================================== --- lib/matplotlib/image.py (revision 2774) +++ lib/matplotlib/image.py (working copy) @@ -106,7 +106,7 @@ self._imcache = None cm.ScalarMappable.changed(self) - def make_image(self): + def make_image(self, magnification=1.0): if self._A is not None: if self._imcache is None: if typecode(self._A) == UInt8: @@ -163,6 +163,8 @@ ty = (ymin-self.axes.viewLim.ymin())/dyintv * numrows l, b, widthDisplay, heightDisplay = self.axes.bbox.get_bounds() + widthDisplay *= magnification + heightDisplay *= magnification im.apply_translation(tx, ty) im.apply_scaling(sx, sy) @@ -184,13 +186,13 @@ def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return - im = self.make_image() + im = self.make_image(renderer.get_image_magnification()) l, b, widthDisplay, heightDisplay = self.axes.bbox.get_bounds() renderer.draw_image(l, b, im, self.axes.bbox) def write_png(self, fname): """Write the image to png file with fname""" - im = self.make_image(False) + im = self.make_image() im.write_png(fname) Index: lib/matplotlib/backends/backend_ps.py =================================================================== --- lib/matplotlib/backends/backend_ps.py (revision 2774) +++ lib/matplotlib/backends/backend_ps.py (working copy) @@ -126,7 +126,7 @@ context instance that controls the colors/styles. """ - def __init__(self, width, height, pswriter): + def __init__(self, width, height, pswriter, dpi=72): RendererBase.__init__(self) self.width = width self.height = height @@ -144,6 +144,7 @@ self.fontname = None self.fontsize = None self.hatch = None + self.image_magnification = dpi/72.0 def set_color(self, r, g, b, store=1): if (r,g,b) != self.color: @@ -352,6 +353,14 @@ lines.append(s[i:limit]) return lines + def get_image_magnification(self): + """ + Get the factor by which to magnify images passed to draw_image. + Allows a backend to have images at a different resolution to other + artists. + """ + return self.image_magnification + def draw_image(self, x, y, im, bbox): """ Draw the Image instance into the current axes; x is the @@ -372,7 +381,8 @@ imagecmd = "false 3 colorimage" hexlines = '\n'.join(self._hex_lines(bits)) - xscale, yscale = w, h + xscale, yscale = ( + w/self.image_magnification, h/self.image_magnification) figh = self.height*72 #print 'values', origin, flipud, figh, h, y @@ -1060,7 +1070,7 @@ self.figure.set_edgecolor(edgecolor) self._pswriter = StringIO() - renderer = RendererPS(width, height, self._pswriter) + renderer = RendererPS(width, height, self._pswriter, dpi=dpi) self.figure.draw(renderer) self.figure.set_facecolor(origfacecolor) @@ -1167,7 +1177,7 @@ self.figure.set_edgecolor(edgecolor) self._pswriter = StringIO() - renderer = RendererPS(width, height, self._pswriter) + renderer = RendererPS(width, height, self._pswriter, dpi=dpi) self.figure.draw(renderer) self.figure.set_facecolor(origfacecolor)
------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel