Skip to content

Commit 90b823e

Browse files
committed
API: add antialiased to interpolation-stage in image
1 parent 2360c59 commit 90b823e

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5791,11 +5791,14 @@ def imshow(self, X, cmap=None, norm=None, *, aspect=None,
57915791
which can be set by *filterrad*. Additionally, the antigrain image
57925792
resize filter is controlled by the parameter *filternorm*.
57935793

5794-
interpolation_stage : {'data', 'rgba'}, default: 'data'
5795-
If 'data', interpolation
5796-
is carried out on the data provided by the user. If 'rgba', the
5797-
interpolation is carried out after the colormapping has been
5798-
applied (visual interpolation).
5794+
interpolation_stage : {'antialiased', 'data', 'rgba'}, default: 'antialiased'
5795+
If 'data', interpolation is carried out on the data provided by the user.
5796+
If 'rgba', the interpolation is carried out in RGBA-space after the
5797+
color-mapping has been applied (visual interpolation). If 'antialiased',
5798+
then 'rgba' is used if downsampling, or upsampling at a rate less than 3.
5799+
If upsampling at a higher rate, then 'data' is used.
5800+
See :doc:`/gallery/images_contours_and_fields/image_antialiasing` for
5801+
a discussion of image antialiasing.
57995802

58005803
alpha : float or array-like, optional
58015804
The alpha blending value, between 0 (transparent) and 1 (opaque).

lib/matplotlib/image.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,21 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
421421
if not unsampled:
422422
if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in (3, 4)):
423423
raise ValueError(f"Invalid shape {A.shape} for image data")
424-
if A.ndim == 2 and self._interpolation_stage != 'rgba':
424+
425+
# if antialiased, this needs to change as window sizes
426+
# change:
427+
interpolation_stage = self._interpolation_stage
428+
if interpolation_stage == 'antialiased':
429+
pos = np.array([[0, 0], [A.shape[1], A.shape[0]]])
430+
disp = t.transform(pos)
431+
dispx = np.abs(np.diff(disp[:, 0])) / A.shape[1]
432+
dispy = np.abs(np.diff(disp[:, 1])) / A.shape[0]
433+
if (dispx < 3) or (dispy < 3):
434+
interpolation_stage = 'rgba'
435+
else:
436+
interpolation_stage = 'data'
437+
438+
if A.ndim == 2 and interpolation_stage == 'data':
425439
# if we are a 2D array, then we are running through the
426440
# norm + colormap transformation. However, in general the
427441
# input data is not going to match the size on the screen so we
@@ -552,7 +566,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
552566
cbook._setattr_cm(self.norm, vmin=s_vmin, vmax=s_vmax):
553567
output = self.norm(resampled_masked)
554568
else:
555-
if A.ndim == 2: # _interpolation_stage == 'rgba'
569+
if A.ndim == 2: # interpolation_stage == 'rgba'
556570
self.norm.autoscale_None(A)
557571
A = self.to_rgba(A)
558572
alpha = self._get_scalar_alpha()
@@ -787,12 +801,14 @@ def set_interpolation_stage(self, s):
787801

788802
Parameters
789803
----------
790-
s : {'data', 'rgba'} or None
804+
s : {'data', 'rgba', 'antialiased'} or None
791805
Whether to apply up/downsampling interpolation in data or RGBA
792806
space. If None, use :rc:`image.interpolation_stage`.
807+
If 'antialiased' we will check upsampling rate and if less
808+
than 3 then use 'rgba', otherwise use 'data'.
793809
"""
794810
s = mpl._val_or_rc(s, 'image.interpolation_stage')
795-
_api.check_in_list(['data', 'rgba'], s=s)
811+
_api.check_in_list(['data', 'rgba', 'antialiased'], s=s)
796812
self._interpolation_stage = s
797813
self.stale = True
798814

0 commit comments

Comments
 (0)