note 91697 deleted from function.imagesetthickness by danbrown
| From: | danbrown@php.net | Date: | Tue, 23 Jun 2009 23:52:00 +0000 |
| Subject: | note 91697 deleted from function.imagesetthickness by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-157309@lists.php.net to get a copy of this message | ||
Note Submitter: rogier
----
The draw_oval function as described by "admin at circle14"
seems nice at first glance, but has it's drawbacks.
Just try the function and one will see that there a numerous empty pixels.
This is due to the nature of the method: given the x and y radius, it's easy to see with e.g.
Pythagoras that we will always have those missing pixels. But those are mathematical details...
One could solve this by taking smaller increments, resulting in drawing even more ellipses. And most
of the time, the number of draws will be a guess.
Furthermore, using "admin at circle14"'s method or the above fix, the number of
ellipses drawn is at least equal to the line thickness, which is pure overkill and a waste of cpu
time.
Instead of this, you can cut the number of steps back to 3.
This example assumes the line thickness will spread evenly on both sides of the line, i.e. drawing a
3px line from 0,1 to 100,1
will would have the same result as drawing a rectangle from 0,0 to 100,2.
Suppose we have an image of 200x200 pixels and a line thickness of 10 on which we'll draw a
centered circle.
The first step is to determine and draw the outer ellipse.
Second, determine and draw the inner ellipse.
Then we'll take the middle ellipse, and use one of the
coordinates that are situated on this middle ellipse to flood-fill the area in between.
This may sound more difficult then it actually is:
<?php
function draw_oval($im, $cx, $cy, $w, $h, $color, $thickness)
{
$thickness = $thickness;
$offset = $thickness/2;
#outer ellipse
imageellipse($im, $cx, $cy, $w+$offset, $h+$offset, $color);
#inner ellipse
imageellipse($im, $cx, $cy, $w-$offset, $h-$offset, $color);
# flood-fill (take note of RADIUS vs Width/Height!)
imagefilltoborder($im, $cx + $w/2, $cy, $color, $color);
}
#test
$h = imagecreatetruecolor(400,400);
draw_oval($h,200,200,200,200, hexdec('ff0000'),10);
header("Content-type: image/png");
imagepng($h);
imagedestroy($h);
#alpha based test
$h = imagecreatetruecolor(400,400);
$c = imagecolorallocatealpha($h,255,0,0,64);
imagesavealpha($h,true);
imagealphablending($h,false); //RTFM!!
draw_oval2($h,200,200,200,200,$c,10);
header("Content-type: image/png");
imagepng($h);
imagedestroy($h);
?>
Also note that if you use alpha-based colors, imagealphablending() must be FALSE and
imagesavealpha() must be TRUE. Also, those colors SHOULD be allocated on the image instead of using
hexdec().
As a last remark, this function is a bit useless when you have a line thickness below 3 pixels.
I'll leave this up to the user to implement this...