imshow without resampling

Eric Firing <efiring@...229...> writes:

I'm not sure who the SVG expert is, and I presume the attached message
applies to pdf as well as ps. I'm bringing it to your attention
because it is suggesting what would seem to be significant
improvements in some backends by taking better advantage of their
native image support. I know nothing about this; would either of you
(or anyone else) like to comment?

Thanks for forwarding this Eric - yes, it applies to pdf.

From: Thomas Robitaille <thomas.robitaille@...149...>

I am using matplotlib to create postscript and SVG files. I am
currently using imshow to show the contents of an array, but this
means that when saving vector graphics files, matplotlib resamples the
image/array onto a finer grid. [...] Postscript and SVG (as languages)
both allow a bitmap of an arbitrary resolution to be scaled,
translated, and rotated without resampling.

This is complicated by the wide variety of interpolation methods offered
by imshow:

        Acceptable values are *None*, 'nearest', 'bilinear',
          'bicubic', 'spline16', 'spline36', 'hanning', 'hamming',
          'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian',
          'bessel', 'mitchell', 'sinc', 'lanczos',

where None means to use the matplotlibrc value, and I think the default
is bicubic. The 'nearest' case is what you get by simply scaling the
original bitmap, so in that case all vector backends could probably
support skipping the interpolation step. The other interpolation methods
could be programmed in Postscript, but that doesn't help with other
backends - though perhaps PDF shadings (gradient fills) could be hacked
to do this. I don't know anything about SVG.

I wonder how the API between the backend and the image object should
look like. Currently the AxesImage object does essentially

        im = self.make_image(renderer.get_image_magnification())
        renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
                            clippath, affine)

and then the backend does things like

        h, w = im.get_size_out()
        [...]
        h,w,s = im.as_rgba_str()
        rgba.shape = (h, w, 4)
        rgb = rgba[:,:,:3]
        a = rgba[:,:,3:]

Instead, I suppose AxesImage needs to first query the renderer if it
supports the interpolation being used, and if so, call a new renderer
method, say draw_interpolated_image(im). Or perhaps it could just call
the new method, and its implementation in RendererBase would fall back
to interpolating the image and calling the old draw_image. Vector
backends could override it to be smarter when possible.

A possibly related thought: the pdf backend could render some kinds of
image files by passing through the encoded image data from the original
file, so when e.g. image_demo3.py does

        lena = Image.open('../data/lena.jpg')
        im = imshow(lena, origin='lower')

the pdf backend could try to read the JPEG file directly, and only
decode it into a bitmap if it happens to be a wrong subtype of JPEG. For
someone who's using big image files, this would decrease both rendering
time and output size, but I don't know if there are any actual users and
if the benefit is large enough to justify the added complexity - but if
we modify the API anyway to support non-resampling imshow, it might be
good to keep that use-case in mind.

···

--
Jouni K. Sepp�nen
http://www.iki.fi/jks