2525from matplotlib ._image import *
2626
2727from matplotlib .transforms import BboxBase
28+ import matplotlib .transforms as mtransforms
2829
2930class _AxesImageBase (martist .Artist , cm .ScalarMappable ):
3031 zorder = 0
@@ -96,6 +97,12 @@ def __init__(self, ax,
9697
9798 self ._imcache = None
9899
100+ # this is an expetimental attribute, if True, unsampled image
101+ # will be drawn using the affine transform that are
102+ # appropriately skewed so that the given postition
103+ # corresponds to the actual position in the coordinate. -JJL
104+ self ._image_skew_coordinate = None
105+
99106 self .update (kwargs )
100107
101108 def get_size (self ):
@@ -204,6 +211,36 @@ def _get_unsampled_image(self, A, image_extents, viewlim):
204211 return im , xmin , ymin , dxintv , dyintv , sx , sy
205212
206213
214+ @staticmethod
215+ def _get_rotate_and_skew_transform (x1 , y1 , x2 , y2 , x3 , y3 ):
216+ """
217+ Retuen a transform that does
218+ (x1, y1) -> (x1, y1)
219+ (x2, y2) -> (x2, y2)
220+ (x2, y1) -> (x3, y3)
221+
222+ It was intended to derive a skew transform that preserve the
223+ lower-left corner (x1, y1) and top-right corner(x2,y2), but
224+ change the the lower-right-corner(x2, y1) to a new position
225+ (x3, y3).
226+ """
227+ tr1 = mtransforms .Affine2D ()
228+ tr1 .translate (- x1 , - y1 )
229+ x2a , y2a = tr1 .transform_point ((x2 , y2 ))
230+ x3a , y3a = tr1 .transform_point ((x3 , y3 ))
231+
232+ inv_mat = 1. / (x2a * y3a - y2a * x3a ) * np .mat ([[y3a , - y2a ],[- x3a , x2a ]])
233+
234+ a , b = (inv_mat * np .mat ([[x2a ], [x2a ]])).flat
235+ c , d = (inv_mat * np .mat ([[y2a ], [0 ]])).flat
236+
237+ tr2 = mtransforms .Affine2D .from_values (a , c , b , d , 0 , 0 )
238+
239+ tr = (tr1 + tr2 + mtransforms .Affine2D ().translate (x1 , y1 )).inverted ().get_affine ()
240+
241+ return tr
242+
243+
207244 def _draw_unsampled_image (self , renderer , gc ):
208245 """
209246 draw unsampled image. The renderer should support a draw_image method
@@ -227,11 +264,23 @@ def _draw_unsampled_image(self, renderer, gc):
227264 im ._url = self .get_url ()
228265
229266 trans = self .get_transform () #axes.transData
230- xx1 , yy1 = trans .transform_non_affine ((xmin , ymin ))
231- xx2 , yy2 = trans .transform_non_affine ((xmin + dxintv , ymin + dyintv ))
267+ xy = trans .transform_non_affine ([(xmin , ymin ),
268+ (xmin + dxintv , ymin + dyintv )])
269+ xx1 , yy1 = xy [0 ]
270+ xx2 , yy2 = xy [1 ]
271+
272+ if self ._image_skew_coordinate :
273+ # skew the image when required.
274+ x_lrc , y_lrc = self ._image_skew_coordinate
275+ xy = trans .transform_non_affine ([(x_lrc , y_lrc )])
276+ xx3 , yy3 = xy [0 ]
277+
278+ tr_rotate_skew = self ._get_rotate_and_skew_transform (xx1 , yy1 , xx2 , yy2 , xx3 , yy3 )
279+ tr = tr_rotate_skew + trans .get_affine ()
280+ else :
281+ tr = trans .get_affine ()
232282
233- renderer .draw_image (gc , xx1 , yy1 , im , xx2 - xx1 , yy2 - yy1 ,
234- trans .get_affine ())
283+ renderer .draw_image (gc , xx1 , yy1 , im , xx2 - xx1 , yy2 - yy1 , tr )
235284
236285
237286 def _check_unsampled_image (self , renderer ):
0 commit comments