1+ from copy import deepcopy
2+ from decorator import decorator
3+ import numpy as np
4+ import cairo
5+
6+ try :
7+ from scipy .misc import imsave
8+ except ImportError :
9+ def imsave (filename , im ):
10+ raise ImportError ("imsave not available: Scipy not found" )
11+
12+
13+ # GEOMETRY
14+
15+ def rotation_matrix (a ):
16+ return np .array ([[np .cos (a ), - np .sin (a ),0 ],
17+ [np .sin (a ), np .cos (a ),0 ],
18+ [0 , 0 , 1.0 ]])
19+
20+ def translation_matrix (xy ):
21+ return np .array ([[1.0 ,0 ,xy [0 ]],
22+ [0 ,1 ,xy [1 ]],
23+ [0 ,0 ,1 ]])
24+
25+ def scaling_matrix (sx ,sy ):
26+ return np .array ([[sx ,0 ,0 ],
27+ [0 ,sy ,0 ],
28+ [0 ,0 ,1 ]])
29+
30+ class Element :
31+
32+ def __init__ (self , draw_method ):
33+ self .draw_method = draw_method
34+ self .matrix = np .eye (3 )
35+
36+ def transform_ctx (self , ctx ):
37+ m = self .matrix
38+ ctx .transform (cairo .Matrix (m [0 ,0 ],m [0 ,1 ],
39+ m [1 ,0 ],m [1 ,1 ],
40+ m [0 ,2 ], m [1 ,2 ]))
41+
42+ def draw (self , surface ):
43+ ctx = surface .new_context ()
44+ self .transform_ctx (ctx )
45+ self .draw_method (ctx )
46+
47+ def set_matrix (self , new_mat ):
48+ new = deepcopy (self )
49+ new .matrix = new_mat
50+ return new
51+
52+ def rotate (self , angle , center = [0 ,0 ]):
53+ center = np .array (center )
54+ mat = (translation_matrix (center )
55+ .dot (rotation_matrix (angle ))
56+ .dot (translation_matrix (- center )))
57+ return self .set_matrix (mat .dot (self .matrix ))
58+
59+
60+ def translate (self , xy ):
61+ return self .set_matrix (translation_matrix (xy ).dot (self .matrix ))
62+
63+ def scale (self , rx , ry = None , center = [0 ,0 ]):
64+ ry = rx if (ry is None ) else ry
65+ center = np .array (center )
66+ mat = (translation_matrix (center )
67+ .dot (scaling_matrix (rx ,ry ))
68+ .dot (translation_matrix (- center )))
69+ return self .set_matrix (mat .dot (self .matrix ))
70+
71+
72+ class Group (Element ):
73+
74+ def __init__ (self , elements ):
75+
76+ self .elements = elements
77+ self .matrix = 1.0 * np .eye (3 )
78+
79+
80+
81+ def draw (self ,surface ):
82+
83+ for e in self .elements :
84+ new_matrix = self .matrix .dot (e .matrix )
85+ e .set_matrix (new_matrix ).draw (surface )
86+
87+ class Surface :
88+
89+ def __init__ (self , width ,height ):
90+ self .width = width
91+ self .height = height
92+ self .surf = cairo .ImageSurface (cairo .FORMAT_ARGB32 , width , height )
93+
94+ def new_context (self ):
95+ return cairo .Context (self .surf )
96+
97+ def to_npimage (self ):
98+ im = 0 + np .frombuffer (self .surf .get_data (), np .uint8 )
99+ im .shape = (self .height , self .width , 4 )
100+ return im [:,:,:3 ]
101+
102+ def write_imagefile (self , filename ):
103+ imsave (filename , self .to_npim ())
104+
105+
106+
107+ def shape_element (draw , xy = (0 ,0 ), angle = 0 , fill_color = None ,
108+ stroke_color = (0 ,0 ,0 ), stroke_width = 0 ):
109+
110+ def new_draw (ctx ):
111+ if fill_color is not None :
112+ draw (ctx )
113+ ctx .set_source_rgb (* fill_color )
114+ ctx .fill ()
115+ if stroke_width > 0 :
116+ draw (ctx )
117+ ctx .set_line_width (stroke_width )
118+ ctx .set_source_rgb (* stroke_color )
119+ ctx .stroke ()
120+
121+ return Element (new_draw ).rotate (angle ).translate (xy )
122+
123+
124+ def rectangle (lx , ly , ** kw ):
125+ return shape_element (lambda c :c .rectangle (- lx / 2 , - ly / 2 , lx , ly ), ** kw )
126+
127+ def square (l , ** kw ):
128+ return rectangle (l ,l , ** kw )
129+
130+ def arc (r , a1 , a2 , ** kw ):
131+ return shape_element (lambda c :c .arc (0 ,0 , r , a1 , a2 ), ** kw )
132+
133+ def circle (r ,** kw ):
134+ return arc (r , 0 , 2 * np .pi , ** kw )
135+
136+ def text (r ,** kw ):
137+ return arc (r , 0 , 2 * np .pi , ** kw )
138+
139+
140+ def line (points , ** kw ):
141+ return shape_element (lambda c :c .arc (0 ,0 , r , a1 , a2 ), ** kw )
142+
143+ def bezier (points , ** kw ):
144+ return shape_element (lambda c :c .arc (0 ,0 , r , a1 , a2 ), ** kw )
145+
146+
147+ if __name__ == "__main__" :
148+
149+ W ,H = 200 , 200
150+
151+ white = np .array ([1 ,1 ,1 ])
152+ black = np .array ([0 ,0 ,0 ])
153+ red = np .array ([0 ,0 ,1 ])
154+
155+ surf = Surface (W ,H )
156+ r1 = rectangle (.2 * W ,.2 * W , xy = [.3 * W ,.3 * W ] , fill_color = red , angle = np .pi / 8 ,
157+ stroke_color = white , stroke_width = .02 * W )
158+ r2 = rectangle (.15 * W ,.15 * W , xy = [.7 * W ,.7 * W ], fill_color = black , stroke_color = white ,
159+ stroke_width = .02 * W )
160+ g = Group ([r1 , r2 ])
161+
162+ rectangle (.1 * W ,.1 * W , xy = [.5 * W ,.5 * W ] , fill_color = red ,
163+ stroke_color = white , stroke_width = .02 * W ).draw (surf )
164+ for i in range (32 ):
165+ g .rotate (i * np .pi / 16 , center = [.5 * W ,.5 * W ]).draw (surf )
166+ surf .to_imagefile ("/home/vz/Documents/Python/MoviePy/gizeh/test.png" )
0 commit comments