|
<?php |
|
/* |
|
* requires pthreads, obviously !! |
|
* usage: |
|
* php mandel.php 1 128 - run with threads, 128 iterations |
|
* php mandel.php 0 128 - run without threads, 128 iterations |
|
* Disclaimer: I know nothing about images, code from: |
|
* http://code.activestate.com/recipes/577680-multi-threaded-mandelbrot-fractal/ |
|
*/ |
|
|
|
class Render extends Thread { |
|
|
|
public function __construct(Mandel $mandel, $id, $max, $img) { |
|
$this->mandel = $mandel; |
|
$this->id = $id; |
|
$this->max = $max; |
|
$this->img = $img; |
|
} |
|
|
|
public function run() { |
|
$mandel = $this->mandel; |
|
|
|
$iterations = $mandel->getIterations(); |
|
$range = range( |
|
$this->id, |
|
$mandel->getSum(), |
|
$this->max); |
|
$width = $mandel->getWidth(); |
|
$height = $mandel->getHeight(); |
|
$draw = $mandel->getDraw(); |
|
$image = $this->img; |
|
|
|
foreach ($range as $pixel) { |
|
$kx = $pixel % $width; |
|
$ky = (int) $pixel / $width; |
|
$a = $draw["xa"] + |
|
$draw["xd"] * $kx / ($width - 1.0); |
|
$b = $b = $draw["ya"] + |
|
$draw["yd"] * $ky / ($height - 1.0); |
|
$x = $a; |
|
$y = $b; |
|
for ($it = 0; $it < $iterations; $it++) { |
|
$x0 = $x * $x - $y * $y + $a; |
|
$y = 2.0 * $x * $y + $b; |
|
$x = $x0; |
|
|
|
if ($x * $x + $y * $y > 4) { |
|
$c = imagecolorallocate( |
|
$image, |
|
($it % 8) * 32, |
|
(16 - $it % 16) * 16, |
|
($it % 16) * 16); |
|
|
|
imagesetpixel( |
|
$image, $kx, $ky, $c); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
protected $mandel; |
|
protected $id; |
|
protected $max; |
|
protected $img; |
|
} |
|
|
|
class Mandel extends Stackable { |
|
|
|
public function __construct($width, $height, $iterations) { |
|
$this->width = $width; |
|
$this->height = $height; |
|
$this->sum = $this->width * |
|
$this->height; |
|
$this->iterations = $iterations; |
|
$this->draw = [ |
|
"xa" => -2, |
|
"xb" => 1.0, |
|
"ya" => -1.5, |
|
"yb" => 1.5, |
|
"xd" => 1.0 - (-2), |
|
"yd" => 1.5 - (-1.5) |
|
]; |
|
} |
|
|
|
public function getIterations() { return $this->iterations; } |
|
public function getDraw() { return $this->draw; } |
|
public function getSum() { return $this->sum; } |
|
public function getWidth() { return $this->width; } |
|
public function getHeight() { return $this->height; } |
|
|
|
public function createImage() { |
|
return imagecreatetruecolor( |
|
$this->width, $this->height); |
|
} |
|
|
|
public function run(){} |
|
|
|
protected $width; |
|
protected $height; |
|
protected $sum; |
|
protected $iterations; |
|
protected $draw; |
|
} |
|
|
|
$threaded = isset($argv[1]) ? intval($argv[1]) : 1; |
|
$iterations = isset($argv[2]) ? intval($argv[2]) : 64; |
|
|
|
$mandel = new Mandel(1920, 1280, $iterations); |
|
$image = $mandel->createImage(); |
|
|
|
$threads = []; # array of threads |
|
$thread = 0; # current thread identifier |
|
$max = 8; # maximum number of threads |
|
|
|
while ($thread<$max) { # create all threads, or not |
|
$threads[$thread] = new Render( |
|
$mandel, $thread, $max, $image); |
|
if (!$threaded) { |
|
$threads[$thread]->run(); |
|
} else $threads[$thread]->start(); |
|
$thread++; |
|
} |
|
|
|
if ($threaded) { |
|
foreach ($threads as $thread) |
|
$thread->join(); |
|
} |
|
|
|
imagepng($image, "mandel.png"); # dump image |
|
?> |
If you want to render Larger images, you may get into memory allocation trouble because of the huge amount of items in
$range.Also the statement
$image = $this->img;will use a lot of memory.I would suggest removing L24-L27 and L31
Replacing L33 with:
And
$imagein L49 and L55 with$this->imgWith this changes I've made a 15306x10240px @ 8 Threads with 256 Iterations without problems.