1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
5 # This file is part of faces.
7 # faces is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # faces is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
25 import matplotlib
.patches
as _patches
26 import matplotlib
.transforms
as _transforms
27 import matplotlib
.artist
as _artist
30 Arrow
= _patches
.Arrow
31 Polygon
= _patches
.Polygon
32 Shadow
= _patches
.Shadow
33 Wedge
= _patches
.Wedge
35 class Rectangle(_patches
.Rectangle
):
36 def __init__(self
, xy
, width
, height
, **kwargs
):
37 _patches
.Rectangle
.__init
__(self
, (0,0), width
, height
, **kwargs
)
41 class RegularPolygon(_patches
.RegularPolygon
):
42 def __init__(self
, xy
, numVertices
, radius
,
43 orientation
=0, **kwargs
):
45 _patches
.Patch
.__init
__(self
, **kwargs
)
48 self
.numVertices
= numVertices
50 self
.orientation
= orientation
51 hstretch
= tools
.HSEP
/ tools
.VSEP
53 theta
= 2*math
.pi
/self
.numVertices
* _patches
.arange(self
.numVertices
) + \
56 xs
= map(lambda t
: self
.xy
[0] + r
* math
.cos(t
) * hstretch
, theta
)
57 ys
= map(lambda t
: self
.xy
[1] + r
* math
.sin(t
), theta
)
59 self
.verts
= zip(xs
, ys
)
66 class Circle(RegularPolygon
):
70 def __init__(self
, xy
, radius
, resolution
=20, # the number of vertices
74 RegularPolygon
.__init
__(self
, xy
,
81 import PIL
.Image
as _Image
82 from matplotlib
.image
import pil_to_array
as _pil_to_array
83 import matplotlib
._image
as _mimage
85 def pil_to_image(pilImage
):
86 if pilImage
.mode
in ('RGBA', 'RGBX'):
87 im
= pilImage
# no need to convert images in rgba format
88 else: # try to convert to an rgba image
90 im
= pilImage
.convert('RGBA')
92 raise RuntimeError('Unknown image mode')
96 return _mimage
.frombuffer(im
.tostring('raw',im
.mode
,0,-1), w
, h
, 1)
99 class Icon(_artist
.Artist
):
100 def __init__(self
, xy
, image
,
101 verticalalignment
='bottom',
102 horizontalalignment
='left'):
103 _artist
.Artist
.__init
__(self
)
105 if isinstance(image
, basestring
):
106 image
=_Image
.open(image
)
108 self
.dpi
= image
.info
.get("dpi", (72, 72))
110 self
.cache
= pil_to_image(self
.image
)
115 def draw(self
, renderer
):
116 if not self
.get_visible(): return
118 xy
= self
._transform
.xy_tup(self
.xy
)
119 renderer
.draw_image(xy
[0], xy
[1], self
.cache
, self
.clipbox
)
122 def get_window_extent(self
, renderer
=None):
123 w
, h
= self
.image
.size
124 xy
= self
._transform
.xy_tup(self
.xy
)
125 dpi
= self
.figure
.get_dpi()
126 return _transforms
.lbwh_to_bbox(xy
[0], xy
[1],
127 w
* dpi
/ self
.dpi
[0],
128 h
* dpi
/ self
.dpi
[1])
131 def make_cache(self
):
132 dpi
= self
.figure
.get_dpi()
133 if self
.cache
.dpi
!= dpi
:
134 w
, h
= self
.image
.size
135 tmp
= self
.image
.resize((int(w
* dpi
/ self
.dpi
[0]),
136 int(h
* dpi
/ self
.dpi
[1])))
137 self
.cache
= pil_to_image(tmp
)
138 self
.cache
.is_grayscale
= False