Hello,
i made a patch which would allow the svg backend to make
rasterized plots according to the dpi given in savefig.
I wanted this in order to have high-res scatter plots.
As you probably know it is hardcoded to 72 dpi right now.
The idea how to, came from the pdf backend. I mostly
copy pasted some code.
I also added a test for it. Some other tests now fail
the image comparison. It is nothing serious apparently.
Probably roundoff errors. Except interp_nearest_vs_none.
The result of which looks now exactly like the pdf which
it did not before.
Also, two other minor changes which i needed
- Compare_images failed for older numy versions. Simple fix ...
- A numpy.float32 variable got passed to the pdfRepr function in
backend_pdf.py. I changed this function to accept this type, too.
Cheers,
Michael
>From 309c93c2e71a7ef8d70deaf1f4d0c6adc77a0472 Mon Sep 17 00:00:00 2001
From: Michael Welter <mwel...@lusi.uni-sb.de>
Date: Sun, 26 Aug 2012 10:10:46 +0200
Subject: [PATCH 1/2] fixed: compare_images for older numpy versions. added:
backend_pdf allows numpy.float32 in pdfRepr
---
lib/matplotlib/backends/backend_pdf.py | 2 +-
lib/matplotlib/testing/compare.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/matplotlib/backends/backend_pdf.py
b/lib/matplotlib/backends/backend_pdf.py
index 4cd8308..7acaddd 100644
--- a/lib/matplotlib/backends/backend_pdf.py
+++ b/lib/matplotlib/backends/backend_pdf.py
@@ -139,7 +139,7 @@ def pdfRepr(obj):
# Floats. PDF does not have exponential notation (1.0e-10) so we
# need to use %f with some precision. Perhaps the precision
# should adapt to the magnitude of the number?
- elif isinstance(obj, float):
+ elif isinstance(obj, (float, np.float32)):
if not np.isfinite(obj):
raise ValueError("Can only output finite numbers in PDF")
r = ("%.10f" % obj).encode('ascii')
diff --git a/lib/matplotlib/testing/compare.py
b/lib/matplotlib/testing/compare.py
index abd4f4f..8563147 100644
--- a/lib/matplotlib/testing/compare.py
+++ b/lib/matplotlib/testing/compare.py
@@ -308,8 +308,8 @@ def compare_images( expected, actual, tol,
in_decorator=False ):
h1p = expectedImage[:,:,i]
h2p = actualImage[:,:,i]
- h1h = np.histogram(h1p, bins=bins)[0]
- h2h = np.histogram(h2p, bins=bins)[0]
+ h1h = np.histogram(h1p, bins=ns)[0]
+ h2h = np.histogram(h2p, bins=ns)[0]
rms += np.sum(np.power((h1h-h2h), 2))
--
1.7.4.1
>From cb1aa376c8aa0e7d977174b53fd72b7fd6badfb5 Mon Sep 17 00:00:00 2001
From: Michael Welter <mwel...@lusi.uni-sb.de>
Date: Sun, 26 Aug 2012 17:18:08 +0200
Subject: [PATCH 2/2] fix: dpi setting should work now for rasterization in svg
backend
---
lib/matplotlib/backends/backend_svg.py | 33 ++++++++++++++++++++-----------
lib/matplotlib/tests/test_image.py | 27 ++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/lib/matplotlib/backends/backend_svg.py
b/lib/matplotlib/backends/backend_svg.py
index 0b9b7ab..f1c709c 100644
--- a/lib/matplotlib/backends/backend_svg.py
+++ b/lib/matplotlib/backends/backend_svg.py
@@ -244,10 +244,11 @@ class RendererSVG(RendererBase):
FONT_SCALE = 100.0
fontd = maxdict(50)
- def __init__(self, width, height, svgwriter, basename=None):
+ def __init__(self, width, height, image_dpi, svgwriter, basename=None):
self.width = width
self.height = height
self.writer = XMLWriter(svgwriter)
+ self.image_dpi = image_dpi # the actual dpi we want to rasterize stuff
with
self._groupd = {}
if not rcParams['svg.image_inline']:
@@ -733,6 +734,11 @@ class RendererSVG(RendererBase):
def option_scale_image(self):
return True
+
+ def get_image_magnification(self):
+ return self.image_dpi/72.0
+
+
def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
attrib = {}
clipid = self._get_clip(gc)
@@ -755,6 +761,17 @@ class RendererSVG(RendererBase):
im.resize(numcols, numrows)
h,w = im.get_size_out()
+
+ if dx is None:
+ w = 72.0*w/self.image_dpi
+ else:
+ w = dx
+
+ if dy is None:
+ h = 72.0*h/self.image_dpi
+ else:
+ h = dy
+
oid = getattr(im, '_gid', None)
url = getattr(im, '_url', None)
if url is not None:
@@ -1113,25 +1130,17 @@ class FigureCanvasSVG(FigureCanvasBase):
def _print_svg(self, filename, svgwriter, fh_to_close=None, **kwargs):
try:
+ image_dpi = kwargs.pop("dpi", 72)
self.figure.set_dpi(72.0)
width, height = self.figure.get_size_inches()
w, h = width*72, height*72
if rcParams['svg.image_noscale']:
- renderer = RendererSVG(w, h, svgwriter, filename)
+ renderer = RendererSVG(w, h, image_dpi, svgwriter, filename)
else:
- # setting mixed renderer dpi other than 72 results in
- # incorrect size of the rasterized image. It seems that the
- # svg internally uses fixed dpi of 72 and seems to cause
- # the problem. I hope someone who knows the svg backends
- # take a look at this problem. Meanwhile, the dpi
- # parameter is ignored and image_dpi is fixed at 72. - JJL
-
- #image_dpi = kwargs.pop("dpi", 72)
- image_dpi = 72
_bbox_inches_restore = kwargs.pop("bbox_inches_restore", None)
renderer = MixedModeRenderer(self.figure,
- width, height, image_dpi, RendererSVG(w, h, svgwriter,
filename),
+ width, height, image_dpi, RendererSVG(w, h, image_dpi,
svgwriter, filename),
bbox_inches_restore=_bbox_inches_restore)
self.figure.draw(renderer)
diff --git a/lib/matplotlib/tests/test_image.py
b/lib/matplotlib/tests/test_image.py
index 4556013..d11a0c9 100644
--- a/lib/matplotlib/tests/test_image.py
+++ b/lib/matplotlib/tests/test_image.py
@@ -160,6 +160,33 @@ def test_no_interpolation_origin():
ax = fig.add_subplot(212)
ax.imshow(np.arange(100).reshape((2, 50)), interpolation='none')
+
+@image_comparison(baseline_images=['rasterize_10dpi'],
extensions=['pdf','svg'], tol=1.5e-3, remove_text=True)
+def test_rasterize_dpi():
+ # This test should check rasterized rendering with high output resolution.
+ # It plots a rasterized line and a normal image with implot. So it will
catch
+ # when images end up in the wrong place in case of non-standard dpi
setting.
+ # Instead of high-res rasterization i use low-res. Therefor the fact that
the
+ # resolution is non-standard is is easily checked by image_comparison.
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ img = np.asarray([[1, 2], [3, 4]])
+
+ fig, axes = plt.subplots(1, 3, figsize = (3, 1))
+
+ axes[0].imshow(img)
+
+ axes[1].plot([0,1],[0,1], linewidth=20., rasterized=True)
+ axes[1].set(xlim = (0,1), ylim = (-1, 2))
+
+ axes[2].plot([0,1],[0,1], linewidth=20.)
+ axes[2].set(xlim = (0,1), ylim = (-1, 2))
+
+ rcParams['savefig.dpi'] = 10
+
+
+
if __name__=='__main__':
import nose
nose.runmodule(argv=['-s','--with-doctest'], exit=False)
--
1.7.4.1
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel