Friday, March 13, 2009

Xiaolin wu circle php implementation

In this post i will finally close this works: Xiaolin Wu look like circle.

Here the function wu_cirlce (helped by distance() and new_color()) that plot an antialiased circle. You need GD supports, the params are commented. Hope this could help someone:


<?php
/*
@author mauro p
*/
function distance($r, $y) {
$real_point = sqrt(pow($r, 2) - pow($y, 2));
return ceil($real_point) - $real_point;
}

function new_color($i) {
return round(($i * 127));
}

/**
* $image a gd image resource
* $r circle's radius
* $color rgb array like array('red' => int(0 : 255), 'green' => int(0 : 255), 'blue' => int(0 : 255))
* $offset_x x axis circle's center
* $offset_y y axis circle's center
*/
function wu_circle($image, $r, $color, $offset_x = null, $offset_y = null) {
$red = $color["red"];
$green = $color["green"];
$blue = $color["blue"];
$offset_x = (is_null($offset_x)) ? 0 : $offset_x;
$offset_y = (is_null($offset_y)) ? 0 : $offset_y;
$x = $xx = $r;
$y = $yy = -1;
$t = 0;
$color = imagecolorallocate($image, $red, $green, $blue);
while($x > $y) {
$y++;
$current_distance = distance($r, $y);
if($current_distance < $t) {
$x--;
}

$trasparency = new_color($current_distance);
$alpha = imagecolorallocatealpha($image, $red, $green, $blue, $trasparency );
$alpha2 = imagecolorallocatealpha($image, $red, $green, $blue, 127 - $trasparency);
imagesetpixel($image, $x + $offset_x, $y + $offset_y, $color);
imagesetpixel($image, $x + $offset_x - 1, $y + $offset_y, $alpha2 );
imagesetpixel($image, $x + $offset_x + 1, $y + $offset_y, $alpha );

imagesetpixel($image, $y + $offset_x, $x + $offset_y, $color);
imagesetpixel($image, $y + $offset_x, $x + $offset_y - 1, $alpha2);
imagesetpixel($image, $y + $offset_x, $x + $offset_y + 1, $alpha);

imagesetpixel($image, $offset_x - $x , $y + $offset_y, $color);
imagesetpixel($image, $offset_x - $x + 1, $y + $offset_y, $alpha2);
imagesetpixel($image, $offset_x - $x - 1, $y + $offset_y, $alpha);

imagesetpixel($image, $offset_x - $y, $x + $offset_y, $color);
imagesetpixel($image, $offset_x - $y, $x + $offset_y - 1, $alpha2);
imagesetpixel($image, $offset_x - $y, $x + $offset_y + 1, $alpha);

imagesetpixel($image, $x + $offset_x, $offset_y - $y, $color);
imagesetpixel($image, $x + $offset_x - 1, $offset_y - $y, $alpha2);
imagesetpixel($image, $x + $offset_x + 1, $offset_y - $y, $alpha);

imagesetpixel($image, $y + $offset_x, $offset_y - $x, $color);
imagesetpixel($image, $y + $offset_x, $offset_y - $x - 1, $alpha);
imagesetpixel($image, $y + $offset_x, $offset_y - $x + 1, $alpha2);

imagesetpixel($image, $offset_x - $y, $offset_y - $x, $color);
imagesetpixel($image, $offset_x - $y, $offset_y - $x - 1, $alpha);
imagesetpixel($image, $offset_x - $y, $offset_y - $x + 1, $alpha2);

imagesetpixel($image, $offset_x - $x, $offset_y - $y, $color);
imagesetpixel($image, $offset_x - $x - 1, $offset_y - $y, $alpha);
imagesetpixel($image, $offset_x - $x + 1, $offset_y - $y, $alpha2);

$t = $current_distance;
}

return $image;
}

$image = imagecreatetruecolor(500, 500);
$c = array("red" => 255, "green" => 0, "blue" => 255);

$image = wu_circle($image, 50, $c, 150, 150);

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);


the result: