gradient option in dialog
[conformal.git] / conformal.py
blob6e0977fcea8bbc610392e8e1fef23a7d4b9ff8b2
1 #!/usr/bin/env python
3 # conformal.py
4 # Copyright (C) 2006-2009 Michael J. Gruber <conformal@drmicha.warpmail.net>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, version 2 of the License.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 import math, cmath
20 from math import *
21 from cmath import *
22 # allow access through module and without
23 from array import array
24 from gimpfu import *
25 try:
26 from fpconst import *
27 import scipy.special
28 except ImportError:
29 pass
31 #import psyco
32 #psyco.full()
34 def conformal(width, height, code, xl, xr, yt, yb, grid, gradient):
35 image = gimp.Image(width, height, RGB)
36 drawables = [ gimp.Layer(image, "Argument", width, height, RGBA_IMAGE, 100, NORMAL_MODE),
37 gimp.Layer(image, "Log. modulus", width, height, RGBA_IMAGE, 35, DARKEN_ONLY_MODE),
38 gimp.Layer(image, "Grid", width, height, RGBA_IMAGE, 10, DARKEN_ONLY_MODE)]
39 image.disable_undo()
40 l = 1
41 for drawable in drawables:
42 image.add_layer(drawable, l)
43 l = -1
45 bpp = drawables[0].bpp
47 gimp.tile_cache_ntiles(2 * (width + 63) / 64)
49 dest_rgns = [ drawable.get_pixel_rgn(0, 0, width, height, True, False) for drawable in drawables ]
50 progress = 0
51 max_progress = width * height
52 gimp.progress_init("Conformally Mapping...")
53 sx = (width-1.0)/(xr-xl)
54 sy = (height-1.0)/(yt-yb)
55 w = complex(0.0)
56 z = complex(0.0)
57 cx, cy = 0, 0
58 ml2 = 2.0*math.log(2) # no need to do this 500*500 times...
59 compiled=compile(code, "compiled code", "exec", 0, 1)
61 for row in range(0, height):
62 args = ()
63 mods = ()
64 sqrs = ()
65 for col in range(0, width):
66 z = col/sx + xl + 1j*( yt - row/sy)
67 exec(compiled)
68 arg = math.atan2(w.imag, w.real)
69 if arg<0.0:
70 arg = arg + 2*math.pi
71 args = args + ( arg/(2*math.pi) ,)
72 try:
73 mod = ( math.log(w.imag**2+w.real**2)/ml2 ) % 1.0
74 except (OverflowError, ValueError):
75 mod=0.0
76 mods = mods + ( mod ,)
77 try:
78 sqr = (int)(w.imag/grid % 2.0) + (int)(w.real/grid % 2.0)
79 except (OverflowError, ValueError):
80 sqr = 0
81 sqrs = sqrs + (bpp-1)*( 255*(sqr % 2) ,) + (255, )
83 samples = gimp.gradient_get_custom_samples(gradient, args)
84 top_p = array("B", [ ((int)(255*samples[col][i]+0.5)) for col in range(0, width) for i in range(bpp) ] )
86 dest_rgns[0][0:width, row] = top_p.tostring()
88 samples = gimp.gradient_get_custom_samples("Default", mods)
89 top_p = array("B", [ ((int)(255*samples[col][i]+0.5)) for col in range(0, width) for i in range(bpp) ] )
90 dest_rgns[1][0:width, row] = top_p.tostring()
92 top_p = array("B", sqrs )
93 dest_rgns[2][0:width, row] = top_p.tostring()
95 progress = progress + width
96 gimp.progress_update(float(progress) / max_progress)
98 for drawable in drawables:
99 drawable.flush()
100 drawable.update(0,0,width,height)
101 pdb.plug_in_edge(image,drawables[2], 10, 0, 0) # amount, WRAP, SOBEL
102 pdb.plug_in_vinvert(image,drawables[2])
104 image.enable_undo()
105 gimp.Display(image)
106 gimp.displays_flush
109 register(
110 "python_fu_conformal",
111 "Colour representation of a conformal map",
112 "Colour representation of a conformal map",
113 "Michael J Gruber",
114 "Michael J Gruber",
115 "2011",
116 "<Toolbox>/File/Create/_Conformal ...",
119 (PF_INT, "width", "width", 512),
120 (PF_INT, "height", "height", 512),
121 (PF_TEXT, "code", "code", "w=z"),
122 (PF_FLOAT, "xl", "x left", -1.0),
123 (PF_FLOAT, "xr", "x right", 1.0),
124 (PF_FLOAT, "yt", "y top", 1.0),
125 (PF_FLOAT, "yb", "y bottom", -1.0),
126 (PF_FLOAT, "grid", "grid", 1.0),
127 (PF_GRADIENT, "gradient", "gradient", "Full saturation spectrum CCW"),
130 conformal)
132 main()