10000 fixed a nearest neighbor interp bug · matplotlib/matplotlib@e959554 · GitHub
[go: up one dir, main page]

Skip to content

Commit e959554

Browse files
committed
fixed a nearest neighbor interp bug
svn path=/trunk/matplotlib/; revision=1307
1 parent 77a9d55 commit e959554

File tree

7 files changed

+175
-72
lines changed

7 files changed

+175
-72
lines changed

API_CHANGES

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
API CHANGES in matplotlib-0.81
22

3+
imshow interpolation arguments changes for advanced interpolation
4+
schemes. See help imshow, particularly the interpolation,
5+
filternorm and filterrad kwargs
6+
37
Contour and contourf now accept masked arrays as the variable to be
48
contoured. Masking works correctly for contour, but a bug remains
59
to be fixed before it will work for contourf. The "badmask" kwarg

CHANGELOG

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
New entries should be added at the top
22

3+
2005-05-10 New image resize options interpolation options. New values
4+
for the interp kwarg are
5+
6+
'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36',
7+
'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
8+
'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
9+
'lanczos', 'blackman'
10+
11+
See help(imshow) for details, particularly the
12+
interpolation, filternorm and filterrad kwargs
13+
14+
315
2005-05-10 Applied Eric's contour mem leak fixes - JDH
416

517
2005-05-10 Extended python agg wrapper and started implementing backend_agg2,

lib/matplotlib/axes.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,9 @@ def imshow(self, X,
16921692
vmax = None,
16931693
origin=None,
16941694
extent=None,
1695-
shape=None):
1695+
shape=None,
1696+
filternorm=1,
1697+
filterrad=4.0):
16961698
"""
16971699
16981700
IMSHOW(X, cmap=None, norm=None, aspect=None, interpolation=None,
@@ -1737,9 +1739,16 @@ def imshow(self, X,
17371739
* aspect is one of: free or preserve. if None, default to rc
17381740
image.aspect value
17391741
1740-
* interpolation is one of: bicubic bilinear blackman100 blackman256
1741-
blackman64 nearest sinc144 sinc256 sinc64 spline16 or spline36.
1742-
If None, default to rc image.interpolation
1742+
* interpolation is one of:
1743+
1744+
'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36',
1745+
'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
1746+
'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
1747+
'lanczos', 'blackman'
1748+
1749+
if interpolation is None, default to rc
1750+
image.interpolation. See also th the filternorm and
1751+
filterrad parameters
17431752
17441753
* norm is a matplotlib.colors.normalize instance; default is
17451754
normalization(). This scales luminance -> 0-1 (Ignored when X is
@@ -1760,18 +1769,36 @@ def imshow(self, X,
17601769
registered with data plots. Default is the image dimensions
17611770
in pixels
17621771
1772+
* shape is for raw buffer images
1773+
1774+
* filternorm is a parameter for the antigrain image resize
1775+
filter. From the antigrain documentation, if normalize=1,
1776+
the filter normalizes integer values and corrects the
1777+
rounding errors. It doesn't do anything with the source
1778+
floating point values, it corrects only integers according
1779+
to the rule of 1.0 which means that any sum of pixel
1780+
weights must be equal to 1.0. So, the filter function
1781+
must produce a graph of the proper shape.
1782+
1783+
* filterrad: the filter radius for filters that have a radius
1784+
parameter, ie when interpolation is one of: 'sinc',
1785+
'lanczos' or 'blackman'
1786+
17631787
"""
17641788

17651789
if not self._hold: self.cla()
17661790

17671791
if norm is not None: assert(isinstance(norm, normalize))
17681792
if cmap is not None: assert(isinstance(cmap, Colormap))
17691793

1770-
im = AxesImage(self, cmap, norm, aspect, interpolation, origin, extent)
1794+
im = AxesImage(self, cmap, norm, aspect, interpolation, origin, extent,
1795+
filternorm=filternorm,
1796+
filterrad=filterrad)
17711797
if norm is None and shape is None:
17721798
im.set_clim(vmin, vmax)
17731799

1774-
im.set_data(X, shape)
1800+
#im.set_data(X, shape)
1801+
im.set_data(X)
17751802
im.set_alpha(alpha)
17761803

17771804
xmin, xmax, ymin, ymax = im.get_extent()
@@ -1907,9 +1934,6 @@ def get_handles():
19071934
if label != '_nolegend_':
19081935
handles.append(line)
19091936
labels.append(label)
1910-
## alternative version -- IMHO less readable:
1911-
#handles, labels = zip([(h, h.get_label()) for h in get_handles()
1912-
# if h.get_label() != '_nolegend_'])
19131937
loc = popd(kwargs, 'loc', 1)
19141938

19151939
elif len(args)==1:

lib/matplotlib/figure.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,8 @@ def colorbar(self, mappable, tickfmt='%1.1f', cax=None, orientation='vertical'):
577577
else:
578578
extent=(cmin, cmax, 0, 1)
579579
coll = cax.imshow(C,
580-
interpolation='nearest',
580+
interpolation='nearest',
581+
#interpolation='bilinear',
581582
origin='lower',
582583
cmap=cmap, norm=norm,
583584
extent=extent)

lib/matplotlib/image.py

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def __init__(self, ax,
2424
interpolation=None,
2525
origin=None,
2626
extent=None,
27+
filternorm=1,
28+
filterrad=4.0,
2729
):
2830

2931
"""
@@ -42,21 +44,30 @@ def __init__(self, ax,
4244

4345
if origin is None: origin = rcParams['image.origin']
4446
self.origin = origin
45-
self._extent = extent
47+
self._extent = extent
48+
self.set_filternorm(filternorm)
49+
self.set_filterrad(filterrad)
50+
4651

4752
# map interpolation strings to module constants
4853
self._interpd = {
49-
'bicubic' : _image.BICUBIC,
50-
'bilinear' : _image.BILINEAR,
51-
'blackman100' : _image.BLACKMAN100,
52-
'blackman256' : _image.BLACKMAN256,
53-
'blackman64' : _image.BLACKMAN64,
54-
'nearest' : _image.NEAREST,
55-
'sinc144' : _image.SINC144,
56-
'sinc256' : _image.SINC256,
57-
'sinc64' : _image.SINC64,
58-
'spline16' : _image.SPLINE16,
59-
'spline36' : _image.SPLINE36,
54+
'nearest' : _image.NEAREST,
55+
'bilinear' : _image.BILINEAR,
56+
'bicubic' : _image.BICUBIC,
57+
'spline16' : _image.SPLINE16,
58+
'spline36' : _image.SPLINE36,
59+
'hanning' : _image.HANNING,
60+
'hamming' : _image.HAMMING,
61+
'hermite' : _image.HERMITE,
62+
'kaiser' : _image.KAISER,
63+
'quadric' : _image.QUADRIC,
64+
'catrom' : _image.CATROM,
65+
'gaussian' : _image.GAUSSIAN,
66+
'bessel' : _image.BESSEL,
67+
'mitchell' : _image.MITCHELL,
68+
'sinc' : _image.SINC,
69+
'lanczos' : _image.LANCZOS,
70+
'blackman' : _image.BLACKMAN,
6071
}
6172

6273
# map aspect ratio strings to module constants
@@ -180,7 +191,8 @@ def make_image(self, flipy):
180191
im.apply_scaling(rx, ry)
181192

182193
#print tx, ty, sx, sy, rx, ry, widthDisplay, heightDisplay
183-
im.resize(int(widthDisplay+0.5), int(heightDisplay+0.5))
194+
im.resize(int(widthDisplay+0.5), int(heightDisplay+0.5),
195+
norm=self._filternorm, radius=self._filterrad)
184196
return im
185197

186198
def draw(self, renderer, *args, **kwargs):
@@ -298,7 +310,34 @@ def get_extent(self):
298310

299311
if self.get_aspect()=='preserve' and sy<sx: sx = sy
300312
return 0, 1.0/sx*dwidth, 0, 1.0/sy*dheight
301-
313+
314+
def set_filternorm(self, filternorm):
315+
"""Set whether the resize filter norms the weights -- see help for imshow
316+
ACCEPTS: 0 or 1
317+
"""
318+
if filternorm:
319+
self._filternorm = 1
320+
else:
321+
self._filternorm = 0
322+
323+
def get_filternorm(self):
324+
'return the filternorm setting'
325+
return self._filternorm
326+
327+
def set_filterrad(self, filterrad):
328+
"""Set the resize filter radius only applicable to some
329+
interpolation schemes -- see help for imshow
330+
331+
ACCEPTS: positive float
332+
"""
333+
r = float(filterrad)
334+
assert(r>0)
335+
self._filterrad = r
336+
337+
def get_filterrad(self):
338+
'return the filterrad setting'
339+
return self._filterrad
340+
302341
class FigureImage(Artist, cm.ScalarMappable):
303342
def __init__(self, fig,
304343
cmap = None,

src/_image.cpp

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -373,54 +373,52 @@ Image::resize(const Py::Tuple& args, const Py::Dict& kwargs) {
373373
switch(interpolation)
374374
{
375375

376-
case 0:
376+
case NEAREST:
377377
{
378-
typedef agg::span_image_filter_rgb_nn<agg::rgba8,
379-
agg::order_bgr,
380-
interpolator_type> span_gen_type;
378+
typedef agg::span_image_filter_rgba_nn<agg::rgba8,agg::order_rgba, interpolator_type> span_gen_type;
381379
typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> renderer_type;
382380

383-
span_gen_type sg(sa, rbufPad, background, interpolator);
381+
span_gen_type sg(sa, *rbufIn, background, interpolator);
384382
renderer_type ri(rb, sg);
385383
agg::render_scanlines(ras, sl, ri);
386384
}
387385
break;
388-
case 1:
389-
case 2:
390-
case 3:
391-
case 4:
392-
case 5:
393-
case 6:
394-
case 7:
395-
case 8:
396-
case 9:
397-
case 10:
398-
case 11:
399-
case 12:
400-
case 13:
401-
case 14:
402-
case 15:
403-
case 16:
386+
case BILINEAR:
387+
case BICUBIC:
388+
case SPLINE16:
389+
case SPLINE36:
390+
case HANNING:
391+
case HAMMING:
392+
case HERMITE:
393+
case KAISER:
394+
case QUADRIC:
395+
case CATROM:
396+
case GAUSSIAN:
397+
case BESSEL:
398< 10000 code class="diff-text syntax-highlighted-line addition">+
case MITCHELL:
399+
case SINC:
400+
case LANCZOS:
401+
case BLACKMAN:
404402
{
405403
agg::image_filter_lut filter;
406404
switch(interpolation)
407405
{
408-
case 1: filter.calculate(agg::image_filter_bilinear(), norm); break;
409-
case 2: filter.calculate(agg::image_filter_bicubic(), norm); break;
410-
case 3: filter.calculate(agg::image_filter_spline16(), norm); break;
411-
case 4: filter.calculate(agg::image_filter_spline36(), norm); break;
412-
case 5: filter.calculate(agg::image_filter_hanning(), norm); break;
413-
case 6: filter.calculate(agg::image_filter_hamming(), norm); break;
414-
case 7: filter.calculate(agg::image_filter_hermite(), norm); break;
415-
case 8: filter.calculate(agg::image_filter_kaiser(), norm); break;
416-
case 9: filter.calculate(agg::image_filter_quadric(), norm); break;
417-
case 10: filter.calculate(agg::image_filter_catrom(), norm); break;
418-
case 11: filter.calculate(agg::image_filter_gaussian(), norm); break;
419-
case 12: filter.calculate(agg::image_filter_bessel(), norm); break;
420-
case 13: filter.calculate(agg::image_filter_mitchell(), norm); break;
421-
case 14: filter.calculate(agg::image_filter_sinc(radius), norm); break;
422-
case 15: filter.calculate(agg::image_filter_lanczos(radius), norm); break;
423-
case 16: filter.calculate(agg::image_filter_blackman(radius), norm); break;
406+
case BILINEAR: filter.calculate(agg::image_filter_bilinear(), norm); break;
407+
case BICUBIC: filter.calculate(agg::image_filter_bicubic(), norm); break;
408+
case SPLINE16: filter.calculate(agg::image_filter_spline16(), norm); break;
409+
case SPLINE36: filter.calculate(agg::image_filter_spline36(), norm); break;
410+
case HANNING: filter.calculate(agg::image_filter_hanning(), norm); break;
411+
case HAMMING: filter.calculate(agg::image_filter_hamming(), norm); break;
412+
case HERMITE: filter.calculate(agg::image_filter_hermite(), norm); break;
413+
case KAISER: filter.calculate(agg::image_filter_kaiser(), norm); break;
414+
case QUADRIC: filter.calculate(agg::image_filter_quadric(), norm); break;
415+
case CATROM: filter.calculate(agg::image_filter_catrom(), norm); break;
416+
case GAUSSIAN: filter.calculate(agg::image_filter_gaussian(), norm); break;
417+
case BESSEL: filter.calculate(agg::image_filter_bessel(), norm); break;
418+
case MITCHELL: filter.calculate(agg::image_filter_mitchell(), norm); break;
419+
case SINC: filter.calculate(agg::image_filter_sinc(radius), norm); break;
420+
case LANCZOS: filter.calculate(agg::image_filter_lanczos(radius), norm); break;
421+
case BLACKMAN: filter.calculate(agg::image_filter_blackman(radius), norm); break;
424422
}
425423

426424
typedef agg::span_image_filter_rgba<agg::rgba8, agg::order_rgba,
@@ -1080,7 +1078,7 @@ _image_module::frombuffer(const Py::Tuple& args) {
10801078
throw Py::ValueError("Cannot get buffer from object.");
10811079

10821080
// Check buffer is required size.
1083-
if (buflen != NUMBYTES)
1081+
if ((size_t)buflen != NUMBYTES)
10841082
throw Py::ValueError("Buffer length must be width * height * 4.");
10851083

10861084
// Copy from input buffer to new buffer for agg.
@@ -1137,17 +1135,24 @@ init_na_image(void) {
11371135

11381136
import_array();
11391137
Py::Dict d = _image->moduleDictionary();
1140-
d["BICUBIC"] = Py::Int(Image::BICUBIC);
1141-
d["BILINEAR"] = Py::Int(Image::BILINEAR);
1142-
d["BLACKMAN100"] = Py::Int(Image::BLACKMAN100);
1143-
d["BLACKMAN256"] = Py::Int(Image::BLACKMAN256);
1144-
d["BLACKMAN64"] = Py::Int(Image::BLACKMAN64);
1138+
11451139
d["NEAREST"] = Py::Int(Image::NEAREST);
1146-
d["SINC144"] = Py::Int(Image::SINC144);
1147-
d["SINC256"] = Py::Int(Image::SINC256);
1148-
d["SINC64"] = Py::Int(Image::SINC64);
1140+
d["BILINEAR"] = Py::Int(Image::BILINEAR);
1141+
d["BICUBIC"] = Py::Int(Image::BICUBIC);
11491142
d["SPLINE16"] = Py::Int(Image::SPLINE16);
11501143
d["SPLINE36"] = Py::Int(Image::SPLINE36);
1144+
d["HANNING"] = Py::Int(Image::HANNING);
1145+
d["HAMMING"] = Py::Int(Image::HAMMING);
1146+
d["HERMITE"] = Py::Int(Image::HERMITE);
1147+
d["KAISER"] = Py::Int(Image::KAISER);
1148+
d["QUADRIC"] = Py::Int(Image::QUADRIC);
1149+
d["CATROM"] = Py::Int(Image::CATROM);
1150+
d["GAUSSIAN"] = Py::Int(Image::GAUSSIAN);
1151+
d["BESSEL"] = Py::Int(Image::BESSEL);
1152+
d["MITCHELL"] = Py::Int(Image::MITCHELL);
1153+
d["SINC"] = Py::Int(Image::SINC);
1154+
d["LANCZOS"] = Py::Int(Image::LANCZOS);
1155+
d["BLACKMAN"] = Py::Int(Image::BLACKMAN);
11511156

11521157
d["ASPECT_FREE"] = Py::Int(Image::ASPECT_FREE);
11531158
d["ASPECT_PRESERVE"] = Py::Int(Image::ASPECT_PRESERVE);

src/_image.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,26 @@ class Image : public Py::PythonExtension<Image> {
3838
Py::Object write_png(const Py::Tuple& args);
3939
Py::Object set_bg(const Py::Tuple& args);
4040

41-
enum { BICUBIC=0, BILINEAR, BLACKMAN100, BLACKMAN256, BLACKMAN64,
42-
NEAREST, SINC144, SINC256, SINC64, SPLINE16, SPLINE36};
41+
enum {NEAREST,
42+
BILINEAR,
43+
BICUBIC,
44+
SPLINE16,
45+
SPLINE36,
46+
HANNING,
47+
HAMMING,
48+
HERMITE,
49+
KAISER,
50+
QUADRIC,
51+
CATROM,
52+
GAUSSIAN,
53+
BESSEL,
54+
MITCHELL,
55+
SINC,
56+
LANCZOS,
57+
BLACKMAN,};
58+
59+
//enum { BICUBIC=0, BILINEAR, BLACKMAN100, BLACKMAN256, BLACKMAN64,
60+
// NEAREST, SINC144, SINC256, SINC64, SPLINE16, SPLINE36};
4361
enum { ASPECT_PRESERVE=0, ASPECT_FREE};
4462

4563
agg::int8u *bufferIn;

0 commit comments

Comments
 (0)
0