Mandelbrot set
This page uses content from Wikipedia. The original article was at Mandelbrot_set. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
You are encouraged to solve this task according to the task description, using any language you may know.
Generate and draw the Mandelbrot set.
BASIC
This is almost exactly the same as the pseudocode from the Wikipedia entry's "For programmers" section (which it's closely based on, of course). The image generated is very blocky ("low-res") due to the selected video mode, but it's fairly accurate.
<lang qbasic>SCREEN 13 WINDOW (-2, 1.5)-(2, -1.5) FOR x0 = -2 TO 2 STEP .01
FOR y0 = -1.5 TO 1.5 STEP .01 x = 0 y = 0
iteration = 0 maxIteration = 223
WHILE (x * x + y * y <= (2 * 2) AND iteration < maxIteration) xtemp = x * x - y * y + x0 y = 2 * x * y + y0
x = xtemp
iteration = iteration + 1 WEND
IF iteration <> maxIteration THEN c = iteration ELSE c = 0 END IF
PSET (x0, y0), c + 32 NEXT
NEXT</lang>
C
This code uses functions from category Raster graphics operations.
<lang c>#include <stdio.h>
- include "imglib.h"
- define MAX_ITERATIONS 500
void draw_mandel(image img){
unsigned int x, y; unsigned int width, height; color_component colour; double x0, y0, xtemp, cr, ci; unsigned int i; width = img->width; height = img->height;
for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { x0 = y0 = 0; cr = ((double)x / (double)width - 0.5); ci = ((double)y / (double)height - 0.5); for (i = 0; x0*x0 + y0*y0 <= 4.0 && i < MAX_ITERATIONS; i++){ xtemp = x0*x0 - y0*y0 + cr; y0 = 2*x0*y0 + ci; x0 = xtemp; } /* points in the set are coloured as white, others are coloured black. */ colour = (i == MAX_ITERATIONS ? 255 : 0); put_pixel_clip(img, x, y, colour, colour, colour); } }
}
- define W 640
- define H 480
int main() {
image img; FILE *o;
img = alloc_img(W, H); draw_mandel(img);
o = fopen("mandel.ppm", "w"); output_ppm(o, img); fclose(o); free_img(img);
}</lang>
Or, using complex numbers, the above draw_mandel() function could be written as follows:
<lang c>#include <complex.c>
void draw_mandel(image img){
unsigned int x, y; unsigned int width, height; color_component colour; double complex z, c; unsigned int i; width = img->width; height = img->height;
for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { z = 0; c = ((double)x / (double)width - 0.5) + ((double)y / (double)height - 0.5)I; for (i = 0; cabs(z) <= 2.0 && i < MAX_ITERATIONS; i++){ z = z*z + c; } /* points in the set are coloured as white, others are coloured black. */ colour = (i == MAX_ITERATIONS ? 255 : 0); put_pixel_clip(img, x, y, colour, colour, colour); } }
}</lang>
C++
This generic function assumes that the image can be accessed like a two-dimensional array of colors. It may be passed a true array (in which case the Mandelbrot set will simply be drawn into that array, which then might be saved as image file), or a class which maps the subscript operator to the pixel drawing routine of some graphics library. In the latter case, there must be functions get_first_dimension and get_second_dimension defined for that type, to be found by argument dependent lookup. The code provides those functions for built-in arrays. <lang cpp>#include <cstdlib>
- include <complex>
// get dimensions for arrays template<typename ElementType, std::size_t dim1, std::size_t dim2>
std::size_t get_first_dimension(ElementType (&a)[dim1][dim2])
{
return dim1;
}
template<typename ElementType, std::size_t dim1, std::size_t dim2>
std::size_t get_second_dimension(ElementType (&a)[dim1][dim2])
{
return dim2;
}
template<typename ColorType, typename ImageType>
void draw_Mandelbrot(ImageType& image, //where to draw the image ColorType set_color, ColorType non_set_color, //which colors to use for set/non-set points double cxmin, double cxmax, double cymin, double cymax,//the rect to draw in the complex plane unsigned int max_iterations) //the maximum number of iterations
{
std::size_t const ixsize = get_first_dimension(ImageType); std::size_t const iysize = get_first_dimension(ImageType); for (std::size_t ix = 0; ix < ixsize; ++ix) for (std::size_t iy = 0; iy < iysize; ++iy) { std::complex c(cxmin + ix/(ixsize-1.0)*(cxmax-cxmin), cymin + iy/(iysize-1.0)*(cymax-cymin)); std::complex z = 0; unsigned int iterations;
for (iterations = 0; iterations < max_iterations && std::abs(z) < 2.0; ++iterations) { z = z*z + c; }
if (iterations == max_iterations) image[ix][iy] = set_color; else image[ix][iy] = non_set_color; }
}</lang>
C#
<lang csharp>using System; using System.Drawing; using System.Drawing.Imaging; using System.Threading; using System.Windows.Forms;
/// <summary> /// Generates bitmap of Mandelbrot Set and display it on the form. /// </summary> public class MandelbrotSetForm : Form {
const double MaxValueExtent = 2.0; Thread thread;
static double CalcMandelbrotSetColor(ComplexNumber c) { // from http://en.wikipedia.org/w/index.php?title=Mandelbrot_set const int MaxIterations = 1000; const double MaxNorm = MaxValueExtent * MaxValueExtent;
int iteration = 0; ComplexNumber z = new ComplexNumber(); do { z = z * z + c; iteration++; } while (z.Norm() < MaxNorm && iteration < MaxIterations); if (iteration < MaxIterations) return (double)iteration / MaxIterations; else return 0; // black }
static void GenerateBitmap(Bitmap bitmap) { double scale = 2 * MaxValueExtent / Math.Min(bitmap.Width, bitmap.Height); for (int i = 0; i < bitmap.Height; i++) { double y = (bitmap.Height / 2 - i) * scale; for (int j = 0; j < bitmap.Width; j++) { double x = (j - bitmap.Width / 2) * scale; double color = CalcMandelbrotSetColor(new ComplexNumber(x, y)); bitmap.SetPixel(j, i, GetColor(color)); } } }
static Color GetColor(double value) { const double MaxColor = 256; const double ContrastValue = 0.2; return Color.FromArgb(0, 0, (int)(MaxColor * Math.Pow(value, ContrastValue))); } public MandelbrotSetForm() { // form creation this.Text = "Mandelbrot Set Drawing"; this.BackColor = System.Drawing.Color.Black; this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; this.MaximizeBox = false; this.StartPosition = FormStartPosition.CenterScreen; this.FormBorderStyle = FormBorderStyle.FixedDialog; this.ClientSize = new Size(640, 640); this.Load += new System.EventHandler(this.MainForm_Load); }
void MainForm_Load(object sender, EventArgs e) { thread = new Thread(thread_Proc); thread.IsBackground = true; thread.Start(this.ClientSize); }
void thread_Proc(object args) { // start from small image to provide instant display for user Size size = (Size)args; int width = 16; while (width * 2 < size.Width) { int height = width * size.Height / size.Width; Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb); GenerateBitmap(bitmap); this.BeginInvoke(new SetNewBitmapDelegate(SetNewBitmap), bitmap); width *= 2; Thread.Sleep(200); } // then generate final image Bitmap finalBitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format24bppRgb); GenerateBitmap(finalBitmap); this.BeginInvoke(new SetNewBitmapDelegate(SetNewBitmap), finalBitmap); }
void SetNewBitmap(Bitmap image) { if (this.BackgroundImage != null) this.BackgroundImage.Dispose(); this.BackgroundImage = image; }
delegate void SetNewBitmapDelegate(Bitmap image);
static void Main() { Application.Run(new MandelbrotSetForm()); }
}
struct ComplexNumber {
public double Re; public double Im;
public ComplexNumber(double re, double im) { this.Re = re; this.Im = im; }
public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y) { return new ComplexNumber(x.Re + y.Re, x.Im + y.Im); }
public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y) { return new ComplexNumber(x.Re * y.Re - x.Im * y.Im, x.Re * y.Im + x.Im * y.Re); }
public double Norm() { return Re * Re + Im * Im; }
}</lang>
D
using
<lang D>module mandelbrot;
import qd;
double lensqr(cdouble c) { return c.re * c.re + c.im * c.im; }
const Limit = 150;
void main() {
screen(640, 480); for (int y = 0; y < screen.h; ++y) { flip; events; for (int x = 0; x < screen.w; ++x) { auto c_x = x * 1.0 / screen.w - 0.5, c_y = y * 1.0 / screen.h - 0.5, c = c_y * 2.0i + c_x * 3.0 - 1.0, z = 0.0i + 0.0, i = 0; for (; i < Limit; ++i) { z = z * z + c; if (lensqr(z) > 4) break; } auto value = cast(ubyte) (i * 255.0 / Limit); pset(x, y, rgb(value, value, value)); } } while (true) { flip; events; }
}</lang>
Forth
This uses grayscale image utilities. <lang Forth>500 value max-iter
- mandel ( gmp F: imin imax rmin rmax -- )
0e 0e { F: imin F: imax F: rmin F: rmax F: Zr F: Zi } dup bheight 0 do i s>f dup bheight s>f f/ imax imin f- f* imin f+ TO Zi dup bwidth 0 do i s>f dup bwidth s>f f/ rmax rmin f- f* rmin f+ TO Zr Zr Zi max-iter begin 1- dup while fover fdup f* fover fdup f* fover fover f+ 4e f< while f- Zr f+ frot frot f* 2e f* Zi f+ repeat fdrop fdrop drop 0 \ for a pretty grayscale image, replace with: 255 max-iter */ else drop 255 then fdrop fdrop over i j rot g! loop loop drop ;
80 24 graymap dup -1e 1e -2e 1e mandel dup gshow free bye</lang>
Fortran
<lang fortran>program mandelbrot
implicit none integer , parameter :: rk = selected_real_kind (9, 99) integer , parameter :: i_max = 800 integer , parameter :: j_max = 600 integer , parameter :: n_max = 100 real (rk), parameter :: x_centre = -0.5_rk real (rk), parameter :: y_centre = 0.0_rk real (rk), parameter :: width = 4.0_rk real (rk), parameter :: height = 3.0_rk real (rk), parameter :: dx_di = width / i_max real (rk), parameter :: dy_dj = -height / j_max real (rk), parameter :: x_offset = x_centre - 0.5_rk * (i_max + 1) * dx_di real (rk), parameter :: y_offset = y_centre - 0.5_rk * (j_max + 1) * dy_dj integer, dimension (i_max, j_max) :: image integer :: i integer :: j integer :: n real (rk) :: x real (rk) :: y real (rk) :: x_0 real (rk) :: y_0 real (rk) :: x_sqr real (rk) :: y_sqr
do j = 1, j_max y_0 = y_offset + dy_dj * j do i = 1, i_max x_0 = x_offset + dx_di * i x = 0.0_rk y = 0.0_rk n = 0 do x_sqr = x ** 2 y_sqr = y ** 2 if (x_sqr + y_sqr > 4.0_rk) then image (i, j) = 255 exit end if if (n == n_max) then image (i, j) = 0 exit end if y = y_0 + 2.0_rk * x * y x = x_0 + x_sqr - y_sqr n = n + 1 end do end do end do open (10, file = 'out.pgm') write (10, '(a/ i0, 1x, i0/ i0)') 'P2', i_max, j_max, 255 write (10, '(i0)') image close (10)
end program mandelbrot</lang>
gnuplot
The output from gnuplot is controlled by setting the appropriate values for the options terminal
and output
.
<lang gnuplot>set terminal png
set output 'mandelbrot.png'</lang>
The following script draws an image of the number of iterations it takes to escape the circle with radius rmax
with a maximum of nmax
.
<lang gnuplot>rmax = 2
nmax = 100
complex (x, y) = x * {1, 0} + y * {0, 1}
mandelbrot (z, z0, n) = n == nmax || abs (z) > rmax ? n : mandelbrot (z ** 2 + z0, z0, n + 1)
set samples 200
set isosamples 200
set pm3d map
set size square
splot [-2 : 2] [-2 : 2] mandelbrot (complex (x, y), complex (x, y), 0) notitle</lang>
The output can be found here.
Haskell
<lang haskell>import Data.Complex
mandelbrot a = iterate (\z -> z^2 + a) a !! 50
main = mapM_ putStrLn [[if magnitude (mandelbrot (x :+ y)) < 2 then '*' else ' '
| x <- [-2, -1.9685 .. 0.5]] | y <- [1, 0.95 .. -1]]</lang>
haXe
This version compiles for flash version 9 or grater. The compilation command is <lang haxe>haxe -swf9 mandelbrot.swf -main Mandelbrot</lang>
<lang haxe>class Mandelbrot extends flash.display.Sprite {
inline static var MAX_ITER = 255;
public static function main() { var w = flash.Lib.current.stage.stageWidth; var h = flash.Lib.current.stage.stageHeight; var mandelbrot = new Mandelbrot(w, h); flash.Lib.current.stage.addChild(mandelbrot); mandelbrot.drawMandelbrot(); }
var image:flash.display.BitmapData; public function new(width, height) { super(); var bitmap:flash.display.Bitmap; image = new flash.display.BitmapData(width, height, false); bitmap = new flash.display.Bitmap(image); this.addChild(bitmap); }
public function drawMandelbrot() { image.lock(); var step_x = 3.0 / (image.width-1); var step_y = 2.0 / (image.height-1); for (i in 0...image.height) { var ci = i * step_y - 1.0; for (j in 0...image.width) { var k = 0; var zr = 0.0; var zi = 0.0; var cr = j * step_x - 2.0; while (k <= MAX_ITER && (zr*zr + zi*zi) <= 4) { var temp = zr*zr - zi*zi + cr; zi = 2*zr*zi + ci; zr = temp; k ++; } paint(j, i, k); } } image.unlock(); }
inline function paint(x, y, iter) { var color = iter > MAX_ITER? 0 : iter * 0x100; image.setPixel(x, y, color); }
}</lang>
J
The characteristic function of the Mandelbrot can be defined as follows: <lang j>mcf=. (<: 2:)@|@(] ((*:@] + [)^:((<: 2:)@|@])^:1000) 0:) NB. 1000 iterations test</lang> The Mandelbrot set can be drawn as follows: <lang j>domain=. |.@|:@({.@[ + ] *~ j./&i.&>/@+.@(1j1 + ] %~ -~/@[))&>/
load'graph' viewmat mcf "0 @ domain (_2j_1 1j1) ; 0.01 NB. Complex interval and resolution</lang>
Modula-3
<lang modula3>MODULE Mandelbrot EXPORTS Main;
IMPORT Wr, Stdio, Fmt, Word;
CONST m = 50;
limit2 = 4.0;
TYPE UByte = BITS 8 FOR [0..16_FF];
VAR width := 200;
height := 200; bitnum: CARDINAL := 0; byteacc: UByte := 0; isOverLimit: BOOLEAN; Zr, Zi, Cr, Ci, Tr, Ti: REAL;
BEGIN
Wr.PutText(Stdio.stdout, "P4\n" & Fmt.Int(width) & " " & Fmt.Int(height) & "\n");
FOR y := 0 TO height - 1 DO FOR x := 0 TO width - 1 DO Zr := 0.0; Zi := 0.0; Cr := 2.0 * FLOAT(x) / FLOAT(width) - 1.5; Ci := 2.0 * FLOAT(y) / FLOAT(height) - 1.0; FOR i := 1 TO m + 1 DO Tr := Zr*Zr - Zi*Zi + Cr; Ti := 2.0*Zr*Zi + Ci; Zr := Tr; Zi := Ti; isOverLimit := Zr*Zr + Zi*Zi > limit2; IF isOverLimit THEN EXIT; END; END; IF isOverLimit THEN byteacc := Word.Xor(Word.LeftShift(byteacc, 1), 16_00); ELSE byteacc := Word.Xor(Word.LeftShift(byteacc, 1), 16_01); END;
INC(bitnum); IF bitnum = 8 THEN Wr.PutChar(Stdio.stdout, VAL(byteacc, CHAR)); byteacc := 0; bitnum := 0; ELSIF x = width - 1 THEN byteacc := Word.LeftShift(byteacc, 8 - (width MOD 8)); Wr.PutChar(Stdio.stdout, VAL(byteacc, CHAR)); byteacc := 0; bitnum := 0 END; Wr.Flush(Stdio.stdout); END; END;
END Mandelbrot.</lang>
OCaml
<lang OCaml>#load "graphics.cma"
open Graphics;;
let mandelbrot xMin xMax yMin yMax xPixels yPixels maxIter =
let rec mandelbrotIterator z c n = if (Complex.norm z) > 2.0 then false else match n with | 0 -> true | n -> let z' = Complex.add (Complex.mul z z) c in mandelbrotIterator z' c (n-1) in Graphics.open_graph (" "^(string_of_int xPixels)^"x"^(string_of_int yPixels)^"+0-0"); let dx = (xMax -. xMin) /. (float_of_int xPixels) and dy = (yMax -. yMin) /. (float_of_int yPixels) in for xi = 0 to xPixels - 1 do for yi = 0 to yPixels - 1 do let c = {Complex.re = xMin +. (dx *. float_of_int xi); Complex.im = yMin +. (dy *. float_of_int yi)} in if (mandelbrotIterator Complex.zero c maxIter) then (Graphics.set_color Graphics.white; Graphics.plot xi yi ) else (Graphics.set_color Graphics.black; Graphics.plot xi yi ) done done;;
mandelbrot (-1.5) 0.5 (-1.0) 1.0 500 500 200; read_line();;</lang>
Octave
This code runs rather slowly and produces coloured Mandelbrot set by accident (output image here).
<lang octave>#! /usr/bin/octave -qf global width = 200; global height = 200; maxiter = 100;
z0 = 0; global cmax = 1 + i; global cmin = -2 - i;
function cs = pscale(c)
global cmax; global cmin; global width; global height; persistent px = (real(cmax-cmin))/width; persistent py = (imag(cmax-cmin))/height; cs = real(cmin) + px*real(c) + i*(imag(cmin) + py*imag(c));
endfunction
ms = zeros(width, height); for x = 0:width-1
for y = 0:height-1 z0 = 0; c = pscale(x+y*i); for ic = 1:maxiter z1 = z0^2 + c; if ( abs(z1) > 2 ) break; endif z0 = z1; endfor ms(x+1, y+1) = ic/maxiter; endfor
endfor
saveimage("mandel.ppm", round(ms .* 255).', "ppm");</lang>
Perl
translation / optimization of the ruby solution <lang perl>use Math::Complex;
sub mandelbrot {
my ($z, $c) = @_[0,0]; for (1 .. 20) { $z = $z * $z + $c; return $_ if abs $z > 2; }
}
for (my $y = 1; $y >= -1; $y -= 0.05) {
for (my $x = -2; $x <= 0.5; $x += 0.0315) {print mandelbrot($x + $y * i) ? ' ' : '#'} print "\n"
}</lang>
PostScript
<lang postscript>%!PS-Adobe-2.0 %%BoundingBox: 0 0 300 200 %%EndComments /origstate save def /ld {load def} bind def /m /moveto ld /g /setgray ld /dot { currentpoint 1 0 360 arc fill } bind def %%EndProlog % param /maxiter 200 def % complex manipulation /complex { 2 array astore } def /real { 0 get } def /imag { 1 get } def /cmul { /a exch def /b exch def
a real b real mul a imag b imag mul sub a real b imag mul a imag b real mul add 2 array astore
} def /cadd { aload pop 3 -1 roll aload pop
3 -1 roll add 3 1 roll add exch 2 array astore
} def /cconj { aload pop neg 2 array astore } def /cabs2 { dup cconj cmul 0 get} def % mandel 200 100 translate -200 1 100 { /x exch def
-100 1 100 { /y exch def /z0 0.0 0.0 complex def 0 1 maxiter { /iter exch def
x 100 div y 100 div complex z0 z0 cmul cadd dup /z0 exch def cabs2 4 gt {exit} if
} for iter maxiter div g x y m dot } for
} for % showpage origstate restore %%EOF</lang>
Python
Translation of the ruby solution <lang python> def mandelbrot(a):
return reduce(lambda z, c: z*z + c, (a for i in xrange(50)), a)
def step(start, step, iterations):
return (start + (i * step) for i in xrange(iterations))
rows = (('*' if abs(mandelbrot(complex(x, y))) < 2 else ' '
for x in step(-2.0, .0315, 80)) for y in step(1, -.05, 41))
print '\n'.join(.join(row) for row in rows) </lang>
R
<lang R>createmandel <- function(zfrom, zto, inc=0.01, maxiter=100) {
x <- c() y <- c() cost <- zfrom while( Re(cost) <= Re(zto) ) { cost <- Re(cost) + Im(zfrom)*1i while ( Im(cost) <= Im(zto) ) { j <- 0 z <- 0 while( (abs(z) < 2) && (j < maxiter)) { z <- z^2 + cost j <- j + 1 } if ( j == maxiter ) { x <- c(x, Re(cost)) y <- c(y, Im(cost)) } cost <- cost + inc*1i } cost <- cost + inc } plot(x,y, pch=".")
}
createmandel(-2-1i, 1+1i)</lang>
Ruby
Text only, prints an 80-char by 41-line depiction. Found here. <lang ruby>require 'complex'
def mandelbrot(a)
Array.new(50,a).inject(a) { |z,c| z*z + c }
end
(1.0).step(-1,-0.05) do |y|
(-2.0).step(0.5,0.0315) do |x| print mandelbrot(Complex(x,y)).abs < 2 ? '*' : ' ' end puts
end</lang>
Uses the text progress bar from Median filter#Ruby <lang ruby>class RGBColour
def self.mandel_colour(i) self.new( 16*(i % 15), 32*(i % 7), 8*(i % 31) ) end
end
class Pixmap
def self.mandelbrot(width, height) mandel = Pixmap.new(width,height) pb = ProgressBar.new(width) if $DEBUG width.times do |x| height.times do |y| x_ish = Float(x - width*11/15) / (width/3) y_ish = Float(y - height/2) / (height*3/10) mandel[x,y] = RGBColour.mandel_colour(mandel_iters(x_ish, y_ish)) end pb.update(x) if $DEBUG end pb.close if $DEBUG mandel end
def self.mandel_iters(cx,cy) x = y = 0.0 count = 0 while Math.hypot(x,y) < 2 and count < 255 x, y = (x**2 - y**2 + cx), (2*x*y + cy) count += 1 end count end
end
Pixmap.mandelbrot(300,300).save('mandel.ppm')</lang>
Scheme
This implementation writes an image of the Mandelbrot set to a plain pgm file. The set itself is drawn in white, while the exterior is drawn in black. <lang scheme>(define x-centre -0.5) (define y-centre 0.0) (define width 4.0) (define i-max 800) (define j-max 600) (define n 100) (define r-max 2.0) (define file "out.pgm") (define colour-max 255) (define pixel-size (/ width i-max)) (define x-offset (- x-centre (* 0.5 pixel-size (+ i-max 1)))) (define y-offset (+ y-centre (* 0.5 pixel-size (+ j-max 1))))
(define (inside? z)
(define (*inside? z-0 z n) (and (< (magnitude z) r-max) (or (= n 0) (*inside? z-0 (+ (* z z) z-0) (- n 1))))) (*inside? z z n))
(define (boolean->integer b)
(if b colour-max 0))
(define (pixel i j)
(boolean->integer (inside? (make-rectangular (+ x-offset (* pixel-size i)) (- y-offset (* pixel-size j))))))
(define (plot)
(with-output-to-file file (lambda () (begin (display "P2") (newline) (display i-max) (newline) (display j-max) (newline) (display colour-max) (newline) (do ((j 1 (+ j 1))) ((> j j-max)) (do ((i 1 (+ i 1))) ((> i i-max)) (begin (display (pixel i j)) (newline))))))))
(plot)</lang>
Tcl
This code makes extensive use of Tk's built-in photo image system, which provides a 32-bit RGBA plotting surface that can be then quickly drawn in any number of places in the application. It uses a computational color scheme that was easy to code... <lang tcl>package require Tk
proc mandelIters {cx cy} {
set x [set y 0.0] for {set count 0} {hypot($x,$y) < 2 && $count < 255} {incr count} { set x1 [expr {$x*$x - $y*$y + $cx}] set y1 [expr {2*$x*$y + $cy}] set x $x1; set y $y1 } return $count
} proc mandelColor {iter} {
set r [expr {16*($iter % 15)}] set g [expr {32*($iter % 7)}] set b [expr {8*($iter % 31)}] format "#%02x%02x%02x" $r $g $b
} image create photo mandel -width 300 -height 300
- Build picture in strips, updating as we go so we have "progress" monitoring
- Also set the cursor to tell the user to wait while we work.
pack [label .mandel -image mandel -cursor watch] update for {set x 0} {$x < 300} {incr x} {
for {set y 0} {$y < 300} {incr y} { set i [mandelIters [expr {($x-220)/100.}] [expr {($y-150)/90.}]] mandel put [mandelColor $i] -to $x $y } update
} .mandel configure -cursor {}</lang>
XSLT
The fact that you can create an image of the Mandelbrot Set with XSLT is sometimes under-appreciated. However, it has been discussed extensively on the internet so is best not reproduced here, not when the code can be executed directly in your browser at that site.