Skip to content

Commit

Permalink
Merge pull request #2044 from mdboom/svg-rasterize
Browse files Browse the repository at this point in the history
Svg rasterize (rebased)
  • Loading branch information
mdboom committed May 24, 2013
2 parents 22c3978 + f288b4e commit f262892
Show file tree
Hide file tree
Showing 8 changed files with 743 additions and 119 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG
@@ -1,3 +1,11 @@
2013-05-18 Added support for arbitrary rasterization resolutions to the
SVG backend. Previously the resolution was hard coded to 72
dpi. Now the backend class takes a image_dpi argument for
its constructor, adjusts the image bounding box accordingly
and forwards a magnification factor to the image renderer.
The code and results now resemble those of the PDF backend.
- MW

2013-05-08 Changed behavior of hist when given stacked=True and normed=True.
Histograms are now stacked first, then the sum is normalized.
Previously, each histogram was normalized, then they were stacked.
Expand Down
4 changes: 4 additions & 0 deletions doc/users/whats_new.rst
Expand Up @@ -1126,3 +1126,7 @@ Here are the 0.98.4 notes from the CHANGELOG::
off automatically when infs or NaNs are present. Also masked
arrays are now converted to arrays with NaNs for consistent
handling of masks and NaNs - MGD and EF

Added support for arbitrary rasterization resolutions to the SVG
backend. - MW
31 changes: 19 additions & 12 deletions lib/matplotlib/backends/backend_svg.py
Expand Up @@ -249,10 +249,11 @@ class RendererSVG(RendererBase):
FONT_SCALE = 100.0
fontd = maxdict(50)

def __init__(self, width, height, svgwriter, basename=None):
def __init__(self, width, height, svgwriter, basename=None, image_dpi=72):
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']:
Expand Down Expand Up @@ -747,6 +748,9 @@ def draw_gouraud_triangles(self, gc, triangles_array, colors_array,
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)
Expand All @@ -769,6 +773,17 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
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:
Expand Down Expand Up @@ -1154,25 +1169,17 @@ def print_svgz(self, filename, *args, **kwargs):

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, svgwriter, filename, image_dpi)
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, svgwriter, filename, image_dpi),
bbox_inches_restore=_bbox_inches_restore)

self.figure.draw(renderer)
Expand Down
30 changes: 30 additions & 0 deletions lib/matplotlib/testing/compare.py
Expand Up @@ -306,6 +306,36 @@ def compare_images( expected, actual, tol, in_decorator=False ):
expectedImage = expectedImage.astype(np.int16)
actualImage = actualImage.astype(np.int16)

# compare the resulting image histogram functions
expected_version = version.LooseVersion("1.6")
found_version = version.LooseVersion(np.__version__)

# On Numpy 1.6, we can use bincount with minlength, which is much faster than
# using histogram
if found_version >= expected_version:
rms = 0

for i in xrange(0, 3):
h1p = expectedImage[:,:,i]
h2p = actualImage[:,:,i]

h1h = np.bincount(h1p.ravel(), minlength=256)
h2h = np.bincount(h2p.ravel(), minlength=256)

rms += np.sum(np.power((h1h-h2h), 2))
else:
rms = 0
ns = np.arange(257)

for i in xrange(0, 3):
h1p = expectedImage[:,:,i]
h2p = actualImage[:,:,i]

h1h = np.histogram(h1p, bins=ns)[0]
h2h = np.histogram(h2p, bins=ns)[0]

rms += np.sum(np.power((h1h-h2h), 2))

rms = calculate_rms(expectedImage, actualImage)

diff_image = make_test_filename(actual, 'failed-diff')
Expand Down

0 comments on commit f262892

Please sign in to comment.