The third result from a Google search of "perl fractal" was this. The site is French, but there is a sample program which uses GD and appears to work quite well (only the comments are in French). Screenshot available here.
If you have a copy of O'Reilly's Advanced Perl Programming available, chapter 18 also has some sample fractal-drawing code.
-fuzzyping | [reply] |
There's examples of this in
Advanced Perl Programming
I don't really remember the details, but this is in the
"Extending Perl" chapter, so i think all of the hardwork
is being done in C code, and the Chapter is really just
showing you how to create a Perl module arround the C code. | [reply] |
#!/usr/bin/perl -w
use strict;
use GD;
use vars qw($P @Q $col $row @colours );
my ($maxcol,
$maxrow,
$max_colours,
$max_iterations,
$max_size ) = (640,350,16,512,4);
my ($XMax,$XMin,$YMax,$YMin) = (1.2,-2.0,1.2,-1.2);
my $deltaP = ($XMax - $XMin) / $maxcol;
my $deltaQ = ($YMax - $YMin) / $maxrow;
$Q[0] = $YMax;
my $image = new GD::Image($maxcol,$maxrow);
for ( 0 .. $max_colours - 1)
{
$colours[$_] = $image->colorAllocate(int(rand(256)),
int(rand(256)),
int(rand(256)));
}
for( 1 .. $maxrow )
{
$Q[$_] = $Q[$_ -1] - $deltaQ;
}
$P = $XMin;
for $col ( 0 .. $maxcol -1 )
{
for $row ( 0 .. $maxrow - 1)
{
my ($X,$Y,$XSquare,$YSquare) = (0,0,0,0);
my $colour = 1;
while (( $colour < $max_iterations ) &&
(($XSquare + $YSquare ) < $max_size ))
{
$XSquare = $X * $X;
$YSquare = $Y * $Y;
$Y *= $X;
$Y += $Y + $Q[$row];
$X = $XSquare - $YSquare + $P;
$colour++;
}
$image->setPixel($col,$row,$colours[$colour % $max_colours]
+);
}
$P += $deltaP;
}
open(PNG,">image$$.png") || die "Cannot open output - $!\n";
binmode(PNG);
print PNG $image->png;
close(PNG);
If you look in the examples for my module Linux::Svgalib there are some further examples. /J\ | [reply] [d/l] |
#!/usr/bin/perl -w
use CGI qw(:standard);
use strict;
use GD;
use vars qw($magnitude $P $Q $scale);
my ($x_centre,$y_centre) = (320,175);
if ( scalar param() < 3 )
{
my @configs = map {chomp; [ split ]} <DATA>;
($P,$Q,$scale) = @{ $configs[rand @configs] };
}
else
{
$P = param('real');
$Q = param('imaginary');
$scale = param('scale');
}
my $image = new GD::Image($x_centre * 2,$y_centre * 2);
my $back_colour = $image->colorAllocate(255,255,255);
my $fore_colour = $image->colorAllocate(0,0,0);
my ($x,$y) = (0.50001,0);
$magnitude = ($P*$P) + ($Q*$Q);
$P = 4*$P/$magnitude;
$Q = -4*$Q/$magnitude;
$scale = $x_centre * $scale;
for ( 1 .. 12000 )
{
my $temp_x = ($x * $P ) - ($y * $Q );
$y = ($x * $Q) + ($y * $P );
my $temp_y = $y;
$x = 1 - $temp_x;
$magnitude = sqrt(($x * $x ) + ($y * $y));
$y = sqrt((-$x + $magnitude)/2);
$x = sqrt(($x + $magnitude)/2);
($x = -$x) if ($temp_y < 0 );
if ( rand() < 0.5 )
{
$x = -$x;
$y = -$y;
}
$x = (1- $x) / 2;
$y = $y / 2;
my $col = int(($scale * ($x - 0.5 )) + $x_centre);
my $row = int($y_centre - ($scale * $y));
if ( ($_ > 0 ) &&
($col >= 0 ) &&
($col < (2 * $x_centre)) &&
($row >= 0 ) &&
($row < ($y_centre * 2 )))
{
$image->setPixel($col,$row,$fore_colour);
}
}
print header('image/png');
binmode(STDOUT);
print $image->png;
__END__
1.646009 0.967049 0.75
2.447261 -0.967049 0.75
1.325508 0.786533 0.75
1.415414 0.856803 0.75
1.255399 0.691977 0.75
2.792809 -0.657593 0.75
3.018153 -0.098854 0.75
2.998122 0.004298 0.75
/J\ | [reply] [d/l] |
A good small introductory book on fractals is Hans Lauwerier's Fractals: Endlessly Repeated Geometrical Figures. It describes the basic theory and includes many programs written in basic which are not too hard to translate to perl.
metadoktor
"The doktor is in." | [reply] |
I went and looked at the Advanced Perl Programming example
of using swig and gd to make a Fractal perl module. Just to
learn about swig, I worked the example out. There are some tricks
you need to work thru, since the swig docs are erratic, and the
APP example has an error between it's header and c file.
Anyways, here are the steps and files to create Fractal.pm with
gd and swig.
I modified the Advanced Perl Programming example to use Png instead of Gif.
Check your perl location for the -I
Run these commands in succession:
1)swig -perl5 fractal.i
2)gcc -fpic -c fractal_wrap.c mandel.c -Dbool=char -I/usr/lib
+/perl5/5.6.0/i586-linux/CORE
3)gcc -shared fractal_wrap.o mandel.o -lgd -o Fractal.so
4)fractal.pl
#fractal.i
############################################
%module Fractal
%{
#include "mandel.h"
%}
%include "mandel.h"
##############################################
#mandel.c
#############################################
#include <math.h>
#include <stdio.h>
#include <gd.h>
#include "mandel.h"
typedef struct {
double r, i;
} complex;
int draw_mandel (char *filename,
int width, int height,
double origin_real,
double origin_imag,
double range,
double max_iterations)
{
complex origin;
int colors[51], color, white, x, y, i;
FILE *out;
gdImagePtr im_out;
origin.r = origin_real; /* Measured from top-left */
origin.i = origin_imag;
if (!(out = fopen(filename, "wb"))) {
fprintf(stderr, "File %s could not be opened\n");
return 1;
}
im_out = gdImageCreate(width, height); /* Create a canvas */
/* Allocate some gray colors. Start from black, and increment r,g,b
values uniformly. This has the effect of varying the luminosity,
while keeping the same hue.
(Black = 0,0,0 and white = 255, 255,255 */
for (i = 0; i < 50; i++) {
color = i * 4;
colors[i] = gdImageColorAllocate(im_out, color,color,color);
}
white = gdImageColorAllocate(im_out, 255,255,255);
/* For each pixel on the canvas do ... */
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
complex z, c ;
int iter;
/* Convert the pixel to an equivalent complex number c,
given the origin and the range. The range acts like an
inverse zoom factor.*/
c.r = origin.r + (double) x / (double) width * range;
c.i = origin.i - (double) y / (double) height * range;
/* Examine each point calculated above to see if repeated
substitutions into an equation like z(next) = z**z + c
remains within a definite boundary.
If after <max_iterations> iterations it still hasn't gone
beyond the white area, it belongs to the Mandelbrot set.
But if it does, we assign it a color depending on how
far the series wants to jump out of bounds*/
color = white;
z.r = z.i = 0.0; /* Starting point */
for (iter = 0; iter < max_iterations; iter++) {
double dist, new_real, new_imag;
/*calculate z = z^2 + c */
/* Recall that z^2 is a^2 - b^2 + 2abi, if z = a + bi, */
new_real = z.r * z.r - z.i * z.i + c.r;
new_imag = 2 * z.r * z.i + c.i;
z.r = new_real; z.i = new_imag;
/* Pythagorean distance from 0,0 */
dist = new_real * new_real + new_imag * new_imag;
if (dist >= 4) {
/* No point on the mandelbrot set is more than 2 units
away from the origin. If it quits the boundary, give
that 'c' an interesting color depending on how far
the series wants to jump out of its bounds */
color = colors[(int) dist % i];
break;
}
}
gdImageSetPixel(im_out, x,y, color);
}
}
gdImagePng(im_out,out);
fclose(out);
return 0;
}
############################################
#mandel.h
#########################################
extern int
draw_mandel (char *filename,
int width, int height,
double origin_real, double origin_imag,
double range, double max_iterations);
######################################
#fractal.pl
#######################################
#!/usr/bin/perl
use Fractal;
Fractal::draw_mandel('mandel.png', 300, 300, -1.5, 1.0,2.0, 20);
# ########### file , width, height, origin x,y max-iterations
#########################################
| [reply] [d/l] |