Mercurial > hg > mood-conductor
comparison visualclient/gradients.py @ 5:1adf97ba90c8
added visual client
author | gyorgyf |
---|---|
date | Thu, 21 Jun 2012 17:14:09 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:02b4c5e122e8 | 5:1adf97ba90c8 |
---|---|
1 #Copyright 2006 DR0ID <dr0id@bluewin.ch> http://mypage.bluewin.ch/DR0ID | |
2 # | |
3 # | |
4 # | |
5 """ | |
6 Allow to draw some gradients relatively easy. | |
7 """ | |
8 | |
9 __author__ = "$Author: DR0ID $" | |
10 __version__= "$Revision: 109 $" | |
11 __date__ = "$Date: 2007-08-09 20:33:32 +0200 (Do, 09 Aug 2007) $" | |
12 | |
13 import pygame | |
14 import math | |
15 | |
16 BLEND_MODES_AVAILABLE = False | |
17 vernum = pygame.vernum | |
18 if vernum[0]>=1 and vernum[1]>=8: | |
19 BLEND_MODES_AVAILABLE = True | |
20 | |
21 | |
22 class ColorInterpolator(object): | |
23 ''' | |
24 ColorInterpolator(distance, color1, color2, rfunc, gfunc, bfunc, afunc) | |
25 | |
26 interpolates a color over the distance using different functions for r,g,b,a | |
27 separately (a= alpha). | |
28 ''' | |
29 def __init__(self, distance, color1, color2, rfunc, gfunc, bfunc, afunc): | |
30 object.__init__(self) | |
31 | |
32 self.rInterpolator = FunctionInterpolator(color1[0], color2[0], distance, rfunc) | |
33 self.gInterpolator = FunctionInterpolator(color1[1], color2[1], distance, gfunc) | |
34 self.bInterpolator = FunctionInterpolator(color1[2], color2[2], distance, bfunc) | |
35 if len(color1)==4 and len(color2)==4: | |
36 self.aInterpolator = FunctionInterpolator(color1[3], color2[3], distance, afunc) | |
37 else: | |
38 self.aInterpolator = FunctionInterpolator(255, 255, distance, afunc) | |
39 | |
40 def eval(self, x): | |
41 ''' | |
42 eval(x) -> color | |
43 | |
44 returns the color at the position 0<=x<=d (actually not bound to this interval). | |
45 ''' | |
46 ## print "colorInterp x", x, self.rInterpolator.eval(x), self.gInterpolator.eval(x), self.bInterpolator.eval(x) | |
47 return [self.rInterpolator.eval(x), | |
48 self.gInterpolator.eval(x), | |
49 self.bInterpolator.eval(x), | |
50 self.aInterpolator.eval(x)] | |
51 | |
52 | |
53 | |
54 class FunctionInterpolator(object): | |
55 ''' | |
56 FunctionINterpolator(startvalue, endvalue, trange, func) | |
57 | |
58 interpolates a function y=f(x) in the range trange with | |
59 startvalue = f(0) | |
60 endvalue = f(trange) | |
61 using the function func | |
62 ''' | |
63 def __init__(self, startvalue, endvalue, trange, func): | |
64 object.__init__(self) | |
65 # function | |
66 self.func = func | |
67 # y-scaling | |
68 self.a = endvalue-startvalue | |
69 if self.a == 0: | |
70 self.a = 1. | |
71 # x-scaling | |
72 if trange!=0: | |
73 self.b = 1./abs(trange) | |
74 else: | |
75 self.b = 1. | |
76 # x-displacement | |
77 self.c = 0 | |
78 # y-displacement | |
79 self.d = min(max(startvalue,0),255) | |
80 | |
81 def eval(self, x): | |
82 ''' | |
83 eval(x)->float | |
84 | |
85 return value at position x | |
86 ''' | |
87 # make sure that the returned value is in [0,255] | |
88 ## return int(round(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255))) | |
89 return int(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255)) | |
90 | |
91 | |
92 | |
93 ##def gradient(surface, | |
94 ## startpoint, | |
95 ## endpoint, | |
96 ## startcolor, | |
97 ## endcolor, | |
98 ## Rfunc = (lambda x:x), | |
99 ## Gfunc = (lambda x:x), | |
100 ## Bfunc = (lambda x:x), | |
101 ## Afunc = (lambda x:1), | |
102 ## type = "line", | |
103 ## mode = None ): | |
104 ## ''' | |
105 ## surface : surface to draw on | |
106 ## startpoint: (x,y) point on surface | |
107 ## endpoint : (x,y) point on surface | |
108 ## startcolor: (r,g,b,a) color at startpoint | |
109 ## endcolor : (r,g,b,a) color at endpoint | |
110 ## Rfunc : function y = f(x) with startcolor =f(0) and endcolor = f(1) where 0 is at startpoint and 1 at endpoint | |
111 ## Gfunc : --- " --- | |
112 ## Bfunc : --- " --- | |
113 ## Afunc : --- " --- | |
114 ## these functions are evaluated in the range 0 <= x <= 1 and 0<= y=f(x) <= 1 | |
115 ## type : "line", "circle" or "rect" | |
116 ## mode : "+", "-", "*", None (how the pixels are drawen) | |
117 ## | |
118 ## returns : surface with the color characteristics w,h = (d, 256) and d = length of endpoint-startpoint | |
119 ## | |
120 ## ''' | |
121 ## dx = endpoint[0]-startpoint[0] | |
122 ## dy = endpoint[1]-startpoint[1] | |
123 ## d = int(round(math.hypot(dx, dy))) | |
124 ## angle = math.degrees( math.atan2(dy, dx) ) | |
125 ## | |
126 ## color = ColorInterpolator(d, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
127 ## | |
128 ## if type=="line": | |
129 ## h = int(2.*math.hypot(*surface.get_size())) | |
130 ### bigSurf = pygame.Surface((d, h)).convert_alpha() | |
131 ## bigSurf = pygame.Surface((d, h), pygame.SRCALPHA)#.convert_alpha() | |
132 ### bigSurf = pygame.Surface((d, 1), pygame.SRCALPHA)#.convert_alpha() | |
133 ## bigSurf.lock() | |
134 ## bigSurf.fill((0,0,0,0)) | |
135 ## bigSurf.set_colorkey((0,0,0,0)) | |
136 ## for x in range(d): | |
137 ## pygame.draw.line(bigSurf, color.eval(x), (x,0), (x,h), 1) | |
138 ### for x in range(d): | |
139 ### bigSurf.set_at((x, 0), color.eval(x)) | |
140 ### bigSurf = pygame.transform.scale(bigSurf, (d, h)) | |
141 ## | |
142 ## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1) | |
143 ## bigSurf.set_colorkey((0,0,0, 0)) | |
144 ## rect = bigSurf.get_rect() | |
145 ## srect = pygame.Rect(rect) | |
146 ## dx = d/2. * math.cos(math.radians(angle)) | |
147 ## dy = d/2. * math.sin(math.radians(angle)) | |
148 ## rect.center = startpoint | |
149 ## rect.move_ip(dx, dy) | |
150 ## bigSurf.unlock() | |
151 ## | |
152 ## elif type=="circle": | |
153 ## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha() | |
154 ## bigSurf.fill((0,0,0,0)) | |
155 ## bigSurf.lock() | |
156 ## for x in range(d, 0, -1): | |
157 ## pygame.draw.circle(bigSurf, color.eval(x), (d,d), x) | |
158 ## bigSurf.unlock() | |
159 ## rect = bigSurf.get_rect() | |
160 ## srect = pygame.Rect(rect) | |
161 ## rect.center = (startpoint[0], startpoint[1]) | |
162 ## | |
163 ## elif type=="rect": | |
164 ## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha() | |
165 ## bigSurf.fill((0,0,0,0)) | |
166 ## c = bigSurf.get_rect().center | |
167 ## bigSurf.lock() | |
168 ## for x in range(d,-1,-1): | |
169 ## r = pygame.Rect(0,0,2*x,2*x) | |
170 ## r.center = c | |
171 ## pygame.draw.rect(bigSurf, color.eval(x), r) | |
172 ## bigSurf.unlock() | |
173 ## bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1) | |
174 ## bigSurf.set_colorkey((0,0,0, 0)) | |
175 ## | |
176 ## rect = bigSurf.get_rect() | |
177 ## srect = pygame.Rect(rect) | |
178 ## rect.center = startpoint | |
179 ## else: | |
180 ## raise NameError("type must be one of \"line\",\"circle\" or \"rect\"") | |
181 ## | |
182 ## if mode is None: | |
183 ## surface.blit(bigSurf, rect, srect) | |
184 ## else: | |
185 ## if mode=="+": | |
186 ## cf = pygame.color.add | |
187 ## elif mode=="*": | |
188 ## cf = pygame.color.multiply | |
189 ## elif mode=="-": | |
190 ## cf = pygame.color.subtract | |
191 ## else: | |
192 ## raise NameError("type must be one of \"+\", \"*\", \"-\" or None") | |
193 ## irect = surface.get_clip().clip(rect) | |
194 ## surface.lock() | |
195 ## for x in range(irect.left, irect.left+irect.width): | |
196 ## for y in range(irect.top, irect.top+irect.height): | |
197 ## surface.set_at((x,y), cf(surface.get_at((x,y)), bigSurf.get_at((x-rect.left, y-rect.top)) ) ) | |
198 ## surface.unlock() | |
199 ## | |
200 ## del bigSurf | |
201 ## char = pygame.Surface((d+1, 257)) | |
202 ### char.fill((0,0,0)) | |
203 ### ox = 0 | |
204 ### oldcol = color.eval(0) | |
205 ### for x in range(d): | |
206 ### col = color.eval(x) | |
207 ### pygame.draw.line(char, (255,0,0), (x, 256-col[0]), (ox, 256-oldcol[0])) | |
208 ### pygame.draw.line(char, (0,255,0), (x, 256-col[1]), (ox, 256-oldcol[1])) | |
209 ### pygame.draw.line(char, (0,0,255), (x, 256-col[2]), (ox, 256-oldcol[2])) | |
210 ### pygame.draw.line(char, (255,255,255), (x, 256-col[3]), (ox, 256-oldcol[3])) | |
211 ### ox = x | |
212 ### oldcol = col | |
213 ### | |
214 ## return char | |
215 | |
216 | |
217 | |
218 | |
219 def vertical(size, startcolor, endcolor): | |
220 """ | |
221 Draws a vertical linear gradient filling the entire surface. Returns a | |
222 surface filled with the gradient (numeric is only 2-3 times faster). | |
223 """ | |
224 height = size[1] | |
225 bigSurf = pygame.Surface((1,height)).convert_alpha() | |
226 dd = 1.0/height | |
227 sr, sg, sb, sa = startcolor | |
228 er, eg, eb, ea = endcolor | |
229 rm = (er-sr)*dd | |
230 gm = (eg-sg)*dd | |
231 bm = (eb-sb)*dd | |
232 am = (ea-sa)*dd | |
233 for y in range(height): | |
234 bigSurf.set_at((0,y), | |
235 (int(sr + rm*y), | |
236 int(sg + gm*y), | |
237 int(sb + bm*y), | |
238 int(sa + am*y)) | |
239 ) | |
240 return pygame.transform.scale(bigSurf, size) | |
241 | |
242 | |
243 def horizontal(size, startcolor, endcolor): | |
244 """ | |
245 Draws a horizontal linear gradient filling the entire surface. Returns a | |
246 surface filled with the gradient (numeric is only 2-3 times faster). | |
247 """ | |
248 width = size[0] | |
249 bigSurf = pygame.Surface((width, 1)).convert_alpha() | |
250 dd = 1.0/width | |
251 sr, sg, sb, sa = startcolor | |
252 er, eg, eb, ea = endcolor | |
253 rm = (er-sr)*dd | |
254 gm = (eg-sg)*dd | |
255 bm = (eb-sb)*dd | |
256 am = (ea-sa)*dd | |
257 for y in range(width): | |
258 bigSurf.set_at((y,0), | |
259 (int(sr + rm*y), | |
260 int(sg + gm*y), | |
261 int(sb + bm*y), | |
262 int(sa + am*y)) | |
263 ) | |
264 return pygame.transform.scale(bigSurf, size) | |
265 | |
266 | |
267 def radial(radius, startcolor, endcolor): | |
268 """ | |
269 Draws a linear raidal gradient on a square sized surface and returns | |
270 that surface. | |
271 """ | |
272 bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha() | |
273 bigSurf.fill((0,0,0,0)) | |
274 dd = -1.0/radius | |
275 sr, sg, sb, sa = endcolor | |
276 er, eg, eb, ea = startcolor | |
277 rm = (er-sr)*dd | |
278 gm = (eg-sg)*dd | |
279 bm = (eb-sb)*dd | |
280 am = (ea-sa)*dd | |
281 | |
282 draw_circle = pygame.draw.circle | |
283 for rad in range(radius, 0, -1): | |
284 draw_circle(bigSurf, (er + int(rm*rad), | |
285 eg + int(gm*rad), | |
286 eb + int(bm*rad), | |
287 ea + int(am*rad)), (radius, radius), rad) | |
288 return bigSurf | |
289 | |
290 def squared(width, startcolor, endcolor): | |
291 """ | |
292 Draws a linear sqared gradient on a square sized surface and returns | |
293 that surface. | |
294 """ | |
295 bigSurf = pygame.Surface((width, width)).convert_alpha() | |
296 bigSurf.fill((0,0,0,0)) | |
297 dd = -1.0/(width/2) | |
298 sr, sg, sb, sa = endcolor | |
299 er, eg, eb, ea = startcolor | |
300 rm = (er-sr)*dd | |
301 gm = (eg-sg)*dd | |
302 bm = (eb-sb)*dd | |
303 am = (ea-sa)*dd | |
304 | |
305 draw_rect = pygame.draw.rect | |
306 for currentw in range((width/2), 0, -1): | |
307 pos = (width/2)-currentw | |
308 draw_rect(bigSurf, (er + int(rm*currentw), | |
309 eg + int(gm*currentw), | |
310 eb + int(bm*currentw), | |
311 ea + int(am*currentw)), pygame.Rect(pos, pos, 2*currentw, 2*currentw )) | |
312 return bigSurf | |
313 | |
314 | |
315 def vertical_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)): | |
316 """ | |
317 Draws a vertical linear gradient filling the entire surface. Returns a | |
318 surface filled with the gradient (numeric is only 2x faster). | |
319 Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define | |
320 how the color changes. | |
321 """ | |
322 height = size[1] | |
323 bigSurf = pygame.Surface((1,height)).convert_alpha() | |
324 color = ColorInterpolator(height, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
325 for y in range(0, height): | |
326 bigSurf.set_at((0,y), color.eval(y+0.1)) | |
327 return pygame.transform.scale(bigSurf, size) | |
328 | |
329 | |
330 def horizontal_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)): | |
331 """ | |
332 Draws a horizontal linear gradient filling the entire surface. Returns a | |
333 surface filled with the gradient (numeric is only 2x faster). | |
334 Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define | |
335 how the color changes. | |
336 """ | |
337 width = size[0] | |
338 bigSurf = pygame.Surface((width, 1)).convert_alpha() | |
339 color = ColorInterpolator(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
340 for y in range(0, width): | |
341 bigSurf.set_at((y, 0), color.eval(y+0.1)) | |
342 return pygame.transform.scale(bigSurf, size) | |
343 | |
344 def radial_func(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0)): | |
345 """ | |
346 Draws a linear raidal gradient on a square sized surface and returns | |
347 that surface. | |
348 """ | |
349 bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha() | |
350 if len(colorkey)==3: | |
351 colorkey += (0,) | |
352 bigSurf.fill(colorkey) | |
353 color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
354 draw_circle = pygame.draw.circle | |
355 for rad in range(radius, 0, -1): | |
356 draw_circle(bigSurf, color.eval(rad), (radius, radius), rad) | |
357 return bigSurf | |
358 | |
359 def radial_func_offset(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0), offset=(0,0)): | |
360 """ | |
361 Draws a linear raidal gradient on a square sized surface and returns | |
362 that surface. | |
363 offset is the amount the center of the gradient is displaced of the center of the image. | |
364 Unfotunately this function ignores alpha. | |
365 """ | |
366 bigSurf = pygame.Surface((2*radius, 2*radius))#.convert_alpha() | |
367 | |
368 mask = pygame.Surface((2*radius, 2*radius), pygame.SRCALPHA)#.convert_alpha() | |
369 mask.fill(colorkey) | |
370 mask.set_colorkey((255,0,255)) | |
371 pygame.draw.circle(mask, (255,0,255), (radius, radius), radius) | |
372 | |
373 if len(colorkey)==3: | |
374 colorkey += (0,) | |
375 bigSurf.fill(colorkey) | |
376 | |
377 color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
378 draw_circle = pygame.draw.circle | |
379 radi = radius + int(math.hypot(offset[0], offset[1])+1) | |
380 for rad in range(radi, 0, -1): | |
381 draw_circle(bigSurf, color.eval(rad), (radius+offset[0], radius+offset[1]), rad) | |
382 | |
383 bigSurf.blit(mask, (0,0)) | |
384 bigSurf.set_colorkey(colorkey) | |
385 return bigSurf | |
386 | |
387 | |
388 def squared_func(width, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), offset=(0,0)): | |
389 """ | |
390 Draws a linear sqared gradient on a square sized surface and returns | |
391 that surface. | |
392 """ | |
393 bigSurf = pygame.Surface((width, width)).convert_alpha() | |
394 bigSurf.fill((0,0,0,0)) | |
395 color = ColorInterpolator(width/2, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
396 draw_rect = pygame.draw.rect | |
397 widthh = width+2*int(max(abs(offset[0]),abs(offset[1]))) | |
398 for currentw in range((widthh/2), 0, -1): | |
399 ## pos = (width/2)-currentw | |
400 rect = pygame.Rect(0, 0, 2*currentw, 2*currentw ) | |
401 rect.center = (width/2+offset[0], width/2+offset[1]) | |
402 draw_rect(bigSurf, color.eval(currentw), rect) | |
403 return bigSurf | |
404 | |
405 def draw_gradient(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0): | |
406 """ | |
407 Instead of returning an Surface, this function draw it directy onto the | |
408 given Surface and returns the rect. | |
409 """ | |
410 dx = endpoint[0]-startpoint[0] | |
411 dy = endpoint[1]-startpoint[1] | |
412 d = int(round(math.hypot(dx, dy))) | |
413 angle = math.degrees( math.atan2(dy, dx) ) | |
414 | |
415 h = int(2.*math.hypot(*surface.get_size())) | |
416 | |
417 bigSurf = horizontal_func((d,h), startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
418 | |
419 ## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1) | |
420 bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1) | |
421 ## bigSurf.set_colorkey((0,0,0, 0)) | |
422 rect = bigSurf.get_rect() | |
423 srect = pygame.Rect(rect) | |
424 dx = d/2. * math.cos(math.radians(angle)) | |
425 dy = d/2. * math.sin(math.radians(angle)) | |
426 rect.center = startpoint | |
427 rect.move_ip(dx, dy) | |
428 if BLEND_MODES_AVAILABLE: | |
429 return surface.blit(bigSurf, rect, None, mode) | |
430 else: | |
431 return surface.blit(bigSurf, rect) | |
432 | |
433 | |
434 def draw_circle(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0): | |
435 """ | |
436 Instead of returning an Surface, this function draw it directy onto the | |
437 given Surface and returns the rect. | |
438 """ | |
439 dx = endpoint[0]-startpoint[0] | |
440 dy = endpoint[1]-startpoint[1] | |
441 radius = int(round(math.hypot(dx, dy))) | |
442 pos = (startpoint[0]-radius, startpoint[1]-radius) | |
443 if BLEND_MODES_AVAILABLE: | |
444 return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos, None, mode) | |
445 else: | |
446 return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos) | |
447 | |
448 def draw_squared(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0): | |
449 """ | |
450 Instead of returning an Surface, this function draw it directy onto the | |
451 given Surface and returns the rect. | |
452 """ | |
453 dx = endpoint[0]-startpoint[0] | |
454 dy = endpoint[1]-startpoint[1] | |
455 angle = math.degrees( math.atan2(dy, dx) ) | |
456 width = 2*int(round(math.hypot(dx, dy))) | |
457 | |
458 bigSurf = squared_func(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
459 | |
460 bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1) | |
461 ## bigSurf.set_colorkey((0,0,0, 0)) | |
462 rect = bigSurf.get_rect() | |
463 rect.center = startpoint | |
464 if BLEND_MODES_AVAILABLE: | |
465 return surface.blit(bigSurf, rect, None, mode) | |
466 else: | |
467 return surface.blit(bigSurf, rect) | |
468 | |
469 | |
470 def chart(startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), scale=None): | |
471 """ | |
472 This returns a Surface where the change of the colors over the distance | |
473 (the width of the image) is showen as a line. | |
474 scale: a float, 1 is not scaling | |
475 """ | |
476 dx = endpoint[0]-startpoint[0] | |
477 dy = endpoint[1]-startpoint[1] | |
478 distance = int(round(math.hypot(dx, dy))) | |
479 color = ColorInterpolator(distance, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc) | |
480 bigSurf = pygame.Surface((distance, 256)) | |
481 bigSurf.fill((0,)*3) | |
482 oldcol = color.eval(0) | |
483 for x in range(distance): | |
484 r, g, b, a = color.eval(x) | |
485 pygame.draw.line(bigSurf, (255, 0, 0, 128), (x-1, oldcol[0]), (x, r)) | |
486 pygame.draw.line(bigSurf, (0, 255, 0, 128), (x-1, oldcol[1]), (x, g)) | |
487 pygame.draw.line(bigSurf, (0, 0, 255, 128), (x-1, oldcol[2]), (x, b)) | |
488 pygame.draw.line(bigSurf, (255, 255, 255, 128), (x-1, oldcol[3]), (x, a)) | |
489 oldcol = (r,g,b,a) | |
490 if scale: | |
491 ## return pygame.transform.scale(bigSurf, size) | |
492 return pygame.transform.rotozoom(bigSurf, 0, scale) | |
493 return pygame.transform.flip(bigSurf, 0, 1) | |
494 #------------------------------------------------------------------------------ | |
495 | |
496 | |
497 | |
498 | |
499 def genericFxyGradient(surf, clip, color1, color2, func, intx, yint, zint=None): | |
500 """ | |
501 genericFxyGradient(size, color1, color2,func, intx, yint, zint=None) | |
502 | |
503 some sort of highfield drawer :-) | |
504 | |
505 surf : surface to draw | |
506 clip : rect on surf to draw in | |
507 color1 : start color | |
508 color2 : end color | |
509 func : function z = func(x,y) | |
510 xint : interval in x direction where the function is evaluated | |
511 yint : interval in y direction where the function is evaluated | |
512 zint : if not none same as yint or xint, if None then the max and min value | |
513 of func is taken as z-interval | |
514 | |
515 color = a*func(b*(x+c), d*(y+e))+f | |
516 """ | |
517 # make shure that x1<x2 and y1<y2 and z1<z2 | |
518 w,h = clip.size | |
519 x1 = min(intx) | |
520 x2 = max(intx) | |
521 y1 = min(yint) | |
522 y2 = max(yint) | |
523 if zint: # if user give us z intervall, then use it | |
524 z1 = min(zint) | |
525 z2 = max(zint) | |
526 else: # look for extrema of function (not best algorithme) | |
527 z1 = func(x1,y1) | |
528 z2 = z1 | |
529 for i in range(w): | |
530 for j in range(h): | |
531 r = func(i,j) | |
532 z1 = min(z1, r) | |
533 z2 = max(z2, r) | |
534 | |
535 x1 = float(x1) | |
536 x2 = float(x2) | |
537 y1 = float(y1) | |
538 y2 = float(y2) | |
539 z1 = float(z1) | |
540 z2 = float(z2) | |
541 if len(color1)==3: | |
542 color1 = list(color1) | |
543 color1.append(255) | |
544 if len(color2)==3: | |
545 color2 = list(color2) | |
546 color2.append(255) | |
547 | |
548 # calculate streching and displacement variables | |
549 a = ((color2[0]-color1[0])/(z2-z1), \ | |
550 (color2[1]-color1[1])/(z2-z1), \ | |
551 (color2[2]-color1[2])/(z2-z1), \ | |
552 (color2[3]-color1[3])/(z2-z1) ) # streching in z direction | |
553 b = (x2-x1)/float(w) # streching in x direction | |
554 d = (y2-y1)/float(h) # streching in y direction | |
555 f = ( color1[0]-a[0]*z1, \ | |
556 color1[1]-a[1]*z1, \ | |
557 color1[2]-a[2]*z1, \ | |
558 color1[3]-a[3]*z1 )# z displacement | |
559 c = x1/b | |
560 e = y1/d | |
561 | |
562 surff = pygame.surface.Surface((w,h)).convert_alpha() | |
563 # generate values | |
564 for i in range(h): | |
565 for j in range(w): | |
566 val = func(b*(j+c), d*(i+e)) | |
567 #clip color | |
568 color = ( max(min(a[0]*val+f[0],255),0), \ | |
569 max(min(a[1]*val+f[1],255),0), \ | |
570 max(min(a[2]*val+f[2],255),0), \ | |
571 max(min(a[3]*val+f[3],255),0) ) | |
572 surff.set_at( (j,i), color ) | |
573 surf.blit(surff, clip) | |
574 | |
575 | |
576 |