2323import pytest
2424
2525
26+ @pytest .fixture
27+ def nonaffine_identity ():
28+ """Non-affine identity transform for compositing with any affine transform"""
29+ class NonAffineIdentityTransform (Transform ):
30+ input_dims = 2
31+ output_dims = 2
32+
33+ def inverted (self ):
34+ return self
35+ return NonAffineIdentityTransform ()
36+
37+
2638@image_comparison (['interp_alpha.png' ], remove_text = True )
2739def test_alpha_interp ():
2840 """Test the interpolation of the alpha channel on RGBA images"""
@@ -1677,7 +1689,7 @@ def test__resample_valid_output():
16771689 np .full (256 , 0.9 )]).reshape (1 , - 1 )),
16781690 ]
16791691)
1680- def test_resample_nonaffine (data , interpolation , expected ):
1692+ def test_resample_nonaffine (data , interpolation , expected , nonaffine_identity ):
16811693 # Test that both affine and nonaffine transforms resample to the correct answer
16821694
16831695 # If the array is constant, the tolerance can be tight
@@ -1693,13 +1705,7 @@ def test_resample_nonaffine(data, interpolation, expected):
16931705
16941706 # Create a nonaffine version of the same transform
16951707 # by compositing with a nonaffine identity transform
1696- class NonAffineIdentityTransform (Transform ):
1697- input_dims = 2
1698- output_dims = 2
1699-
1700- def inverted (self ):
1701- return self
1702- nonaffine_transform = NonAffineIdentityTransform () + affine_transform
1708+ nonaffine_transform = nonaffine_identity + affine_transform
17031709
17041710 nonaffine_result = np .empty_like (expected )
17051711 mimage .resample (data , nonaffine_result , nonaffine_transform ,
@@ -1871,3 +1877,28 @@ def test_interpolation_stage_rgba_respects_alpha_param(fig_test, fig_ref, intp_s
18711877 (im_rgb , new_array_alpha .reshape ((ny , nx , 1 ))), axis = - 1
18721878 ), interpolation_stage = intp_stage
18731879 )
1880+
1881+
1882+ @image_comparison (['nn_pixel_alignment.png' ])
1883+ def test_nn_pixel_alignment (nonaffine_identity ):
1884+ fig , axs = plt .subplots (2 , 3 )
1885+
1886+ N = [3 , 7 , 11 ]
1887+
1888+ for j in range (3 ):
1889+ # In each column, the plots use the same data array
1890+ data = np .arange (N [j ]** 2 ).reshape ((N [j ], N [j ])) % 4
1891+ seps = np .arange (- 0.5 , N [j ])
1892+
1893+ for i in range (2 ):
1894+ if i == 0 :
1895+ # Top row uses an affine transform
1896+ axs [i , j ].imshow (data , cmap = 'Grays' , interpolation = 'nearest' )
1897+ else :
1898+ # Bottom row uses a non-affine transform
1899+ axs [i , j ].imshow (data , cmap = 'Grays' , interpolation = 'nearest' ,
1900+ transform = nonaffine_identity + axs [i , j ].transData )
1901+
1902+ axs [i , j ].set_axis_off ()
1903+ axs [i , j ].vlines (seps , - 1 , N [j ], lw = 0.5 , color = 'red' , ls = 'dashed' )
1904+ axs [i , j ].hlines (seps , - 1 , N [j ], lw = 0.5 , color = 'red' , ls = 'dashed' )
0 commit comments