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.
22 # allow access through module and without
23 from array
import array
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
)]
41 for drawable
in drawables
:
42 image
.add_layer(drawable
, l
)
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
]
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
)
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
):
65 for col
in range(0, width
):
66 z
= col
/sx
+ xl
+ 1j
*( yt
- row
/sy
)
68 arg
= math
.atan2(w
.imag
, w
.real
)
71 args
= args
+ ( arg
/(2*math
.pi
) ,)
73 mod
= ( math
.log(w
.imag
**2+w
.real
**2)/ml2
) % 1.0
74 except (OverflowError, ValueError):
76 mods
= mods
+ ( mod
,)
78 sqr
= (int)(w
.imag
/grid
% 2.0) + (int)(w
.real
/grid
% 2.0)
79 except (OverflowError, ValueError):
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
:
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])
110 "python_fu_conformal",
111 "Colour representation of a conformal map",
112 "Colour representation of a conformal map",
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"),