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

Skip to content

Commit 75097f9

Browse files
committed
experimental support of Image._image_skew_coordinate
svn path=/trunk/matplotlib/; revision=8099
1 parent ea656bb commit 75097f9

2 files changed

Lines changed: 104 additions & 4 deletions

File tree

examples/api/demo_affine_image.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python
2+
3+
4+
"""
5+
For the backends that supports draw_image with optional affine
6+
transform (e.g., ps backend), the image of the output should
7+
have its boundary matches the red rectangles.
8+
"""
9+
10+
import numpy as np
11+
import matplotlib.cm as cm
12+
import matplotlib.mlab as mlab
13+
import matplotlib.pyplot as plt
14+
import matplotlib.transforms as mtransforms
15+
16+
def get_image():
17+
delta = 0.25
18+
x = y = np.arange(-3.0, 3.0, delta)
19+
X, Y = np.meshgrid(x, y)
20+
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
21+
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
22+
Z = Z2-Z1 # difference of Gaussians
23+
return Z
24+
25+
def imshow_affine(ax, z, *kl, **kwargs):
26+
im = ax.imshow(z, *kl, **kwargs)
27+
x1, x2, y1, y2 = im.get_extent()
28+
im._image_skew_coordinate = (x2, y1)
29+
return im
30+
31+
32+
if 1:
33+
ax = plt.subplot(111)
34+
Z = get_image()
35+
im = imshow_affine(ax, Z, interpolation='nearest', cmap=cm.jet,
36+
origin='lower', extent=[-2, 4, -3, 2])
37+
38+
trans_data2 = mtransforms.Affine2D().rotate_deg(30) + ax.transData
39+
im.set_transform(trans_data2)
40+
41+
# display intended extent of the image
42+
x1, x2, y1, y2 = im.get_extent()
43+
x3, y3 = x2, y1
44+
45+
ax.plot([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1], "r--", lw=3,
46+
transform=trans_data2)
47+
48+
ax.set_xlim(-3, 5)
49+
ax.set_ylim(-4, 4)
50+
51+
plt.savefig("demo_affine_image")

lib/matplotlib/image.py

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from matplotlib._image import *
2626

2727
from matplotlib.transforms import BboxBase
28+
import matplotlib.transforms as mtransforms
2829

2930
class _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

Comments
 (0)