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

Reply via email to