Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 981818c

Browse files
committed
ENH: anti-alias down-sampled images
1 parent 9e7a235 commit 981818c

File tree

4 files changed

+51
-10
lines changed

4 files changed

+51
-10
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5482,17 +5482,25 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
54825482
The interpolation method used. If *None*
54835483
:rc:`image.interpolation` is used, which defaults to 'nearest'.
54845484
5485-
Supported values are 'none', 'nearest', 'bilinear', 'bicubic',
5486-
'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser',
5487-
'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
5488-
'lanczos'.
5485+
Supported values are 'none', 'antialiased', 'nearest', 'bilinear',
5486+
'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite',
5487+
'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
5488+
'sinc', 'lanczos'.
54895489
54905490
If *interpolation* is 'none', then no interpolation is performed
54915491
on the Agg, ps, pdf and svg backends. Other backends will fall back
54925492
to 'nearest'. Note that most SVG renders perform interpolation at
54935493
rendering and that the default interpolation method they implement
54945494
may differ.
54955495
5496+
If *interpolation* is the default 'antialiased', then 'nearest'
5497+
interpolation is used if the image is upsampled by more than a
5498+
factor of three (i.e. the number of display pixels is at least three
5499+
times the size of the data array). If the upsampling rate is
5500+
smaller than 3, or the image is downsampled, then 'hanning'
5501+
interpolation is used to act as an anti-aliasing filter, unless the
5502+
image happens to be upsampled by exactly a factor of two or one.
5503+
54965504
See
54975505
:doc:`/gallery/images_contours_and_fields/interpolation_methods`
54985506
for an overview of the supported interpolation methods.

lib/matplotlib/image.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
# map interpolation strings to module constants
3535
_interpd_ = {
36+
'antialiased': None, # this will use nearest or Hanning if downsampled
3637
'none': _image.NEAREST, # fall back to nearest when not supported
3738
'nearest': _image.NEAREST,
3839
'bilinear': _image.BILINEAR,
@@ -168,6 +169,25 @@ def _resample(
168169
allocating the output array and fetching the relevant properties from the
169170
Image object *image_obj*.
170171
"""
172+
173+
# decide if we need to apply anti-aliasing if the data is upsampled:
174+
# compare the number of displayed pixels to the number of
175+
# the data pixels.
176+
interpolation = image_obj.get_interpolation()
177+
if interpolation == 'antialiased':
178+
samplerate = transform.transform([A.shape[1], 0])[0] / A.shape[1]
179+
# don't antialias if upsampling by an integer number or
180+
# if zooming in more than a factor of 3
181+
# do antialiasing....
182+
# compare the number of displayed pixels to the number of
183+
# the data pixels.
184+
samplerate = transform.transform([A.shape[1], 0])[0] / A.shape[1]
185+
if (samplerate < 3 and
186+
np.abs(int(samplerate) - (samplerate)) > 0.0001):
187+
interpolation = 'hanning'
188+
else:
189+
interpolation = 'nearest'
190+
171191
out = np.zeros(out_shape + data.shape[2:], data.dtype) # 2D->2D, 3D->3D.
172192
if resample is None:
173193
resample = image_obj.get_resample()
@@ -354,6 +374,20 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
354374
out_height = int(out_height_base)
355375
out_shape = (out_height, out_width)
356376

377+
# decide if we are going to do anti-aliasing or not on the image
378+
interpolation = self.get_interpolation()
379+
if interpolation == 'antialiased':
380+
# default
381+
interpolation = 'nearest'
382+
# do antialiasing....
383+
# compare the number of displayed pixels to the number of
384+
# the data pixels.
385+
samplerate = t.transform([A.shape[1], 0])[0] / A.shape[1]
386+
if (samplerate < 3 and
387+
np.abs(int(samplerate) - (samplerate)) > 0.0001):
388+
# do anti-aliasing
389+
interpolation = 'hanning'
390+
357391
if not unsampled:
358392
if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in (3, 4)):
359393
raise ValueError(f"Invalid shape {A.shape} for image data")
@@ -432,7 +466,6 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
432466
A_scaled += 0.1
433467
# resample the input data to the correct resolution and shape
434468
A_resampled = _resample(self, A_scaled, out_shape, t)
435-
436469
# done with A_scaled now, remove from namespace to be sure!
437470
del A_scaled
438471
# un-scale the resampled data to approximately the
@@ -708,9 +741,9 @@ def set_interpolation(self, s):
708741
709742
Parameters
710743
----------
711-
s : {'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', \
712-
'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian', \
713-
'bessel', 'mitchell', 'sinc', 'lanczos', 'none'}
744+
s : {'antialiased', 'nearest', 'bilinear', 'bicubic', 'spline16',
745+
'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', \
746+
'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', 'none'}
714747
715748
"""
716749
if s is None:

lib/matplotlib/rcsetup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ def _validate_linestyle(ls):
11001100
'mathtext.fallback_to_cm': [True, validate_bool],
11011101

11021102
'image.aspect': ['equal', validate_aspect], # equal, auto, a number
1103-
'image.interpolation': ['nearest', validate_string],
1103+
'image.interpolation': ['antialiased', validate_string],
11041104
'image.cmap': ['viridis', validate_string], # gray, jet, etc.
11051105
'image.lut': [256, validate_int], # lookup table
11061106
'image.origin': ['upper',

matplotlibrc.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@
557557
## * IMAGES *
558558
## ***************************************************************************
559559
#image.aspect : equal ## {equal, auto} or a number
560-
#image.interpolation : nearest ## see help(imshow) for options
560+
#image.interpolation : antialiased ## see help(imshow) for options
561561
#image.cmap : viridis ## A colormap name, gray etc...
562562
#image.lut : 256 ## the size of the colormap lookup table
563563
#image.origin : upper ## {lower, upper}

0 commit comments

Comments
 (0)