8000 Fix an off-by-half-pixel bug when resampling under a nonaffine transform · matplotlib/matplotlib@e0d192d · GitHub
[go: up one dir, main page]

Skip to content

Commit e0d192d

Browse files
committed
Fix an off-by-half-pixel bug when resampling under a nonaffine transform
1 parent a916809 commit e0d192d

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

lib/matplotlib/tests/test_image.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import urllib.request
1010

1111
import numpy as np
12-
from numpy.testing import assert_array_equal
12+
from numpy.testing import assert_allclose, assert_array_equal
1313
from PIL import Image
1414

1515
import matplotlib as mpl
@@ -18,7 +18,7 @@
1818
from matplotlib.image import (AxesImage, BboxImage, FigureImage,
1919
NonUniformImage, PcolorImage)
2020
from matplotlib.testing.decorators import check_figures_equal, image_comparison
21-
from matplotlib.transforms import Bbox, Affine2D, TransformedBbox
21+
from matplotlib.transforms import Bbox, Affine2D, Transform, TransformedBbox
2222
import matplotlib.ticker as mticker
2323

2424
import pytest
@@ -1641,6 +1641,41 @@ def test__resample_valid_output():
16411641
resample(np.zeros((9, 9)), out)
16421642

16431643

1644+
@pytest.mark.parametrize("data, interpolation, expected",
1645+
[(np.array([[0.1, 0.3, 0.2]]), mpl._image.NEAREST,
1646+
np.array([[0.1, 0.1, 0.1, 0.3, 0.3, 0.3, 0.3, 0.2, 0.2, 0.2]])),
1647+
(np.array([[0.1, 0.3, 0.2]]), mpl._image.BILINEAR,
1648+
np.array([[0.1, 0.1, 0.15078125, 0.21096191, 0.27033691,
1649+
0.28476562, 0.2546875, 0.22460938, 0.20002441, 0.20002441]])),
1650+
]
1651+
)
1652+
def test__resample_nonaffine(data, interpolation, expected):
1653+
# Test that equivalent affine and nonaffine transforms resample the same
1654+
1655+
# Create a simple affine transform for scaling the input array
1656+
affine_transform = Affine2D().scale(sx=expected.shape[1] / data.shape[1], sy=1)
1657+
1658+
affine_result = np.empty_like(expected)
1659+
mpl._image.resample(data, affine_result, affine_transform,
1660+
interpolation=interpolation)
1661+
assert_allclose(affine_result, expected)
1662+
1663+
# Create a nonaffine version of the same transform
1664+
# by compositing with a nonaffine identity transform
1665+
class NonAffineIdentityTransform(Transform):
1666+
input_dims = 2
1667+
output_dims = 2
1668+
1669+
def inverted(self):
1670+
return self
1671+
nonaffine_transform = NonAffineIdentityTransform() + affine_transform
1672+
1673+
nonaffine_result = np.empty_like(expected)
1674+
mpl._image.resample(data, nonaffine_result, nonaffine_transform,
1675+
interpolation=interpolation)
1676+
assert_allclose(nonaffine_result, expected)
1677+
1678+
16441679
def test_axesimage_get_shape():
16451680
# generate dummy image to test get_shape method
16461681
ax = plt.gca()

src/_image_wrapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ _get_transform_mesh(const py::object& transform, const py::ssize_t *dims)
6666

6767
for (auto y = 0; y < dims[0]; ++y) {
6868
for (auto x = 0; x < dims[1]; ++x) {
69-
*p++ = (double)x;
70-
*p++ = (double)y;
69+
*p++ = (double)x + 0.5;
70+
*p++ = (double)y + 0.5;
7171
}
7272
}
7373

0 commit comments

Comments
 (0)
0