Rendering Antialiased Filled Arcs, Ellipses and Circles with PHP and GD
published: 10 Aug 2006, last updated: 29 Dec 2012
With PHP, or more precisely the GD library, you can draw filled elliptical arcs, ellipses and circles, but antialiasing is not supported. I have written a PHP function that renders them with antialiasing.
Examples
The following images were created with the PHP function. Click on them to see larger versions.
Download the Code
If you use this script, a link back to this website would be appreciated but is not required.
- Image Smooth Arc 1.1 (4.4 kB)
The latest version and an example file.
- Image Smooth Arc Optimized 1.0 (3.1 kB)
An optimized version that limits angles to n*PI/2 or n*90° (n = integer). You should use this version if you draw antialiased rounded corners, full circles, etc. It is a bit faster and looks better at small sizes.
Older Versions
- Image Smooth Arc 0.5 (1.7 kB)
The initial version (0.5). You should not use this.
Other Downloads
- PHP Class that creates Rounded Corners 2.0 (4.7 kB)
This Version is able to cache the output. The author of this class is Laurent Thoulon
- PHP Class that creates Rounded Corners 1.0 (3.6 kB)
The author of this class is Laurent Thoulon
Documentation
Description
The function draws antialiased elliptical arcs, ellipses or circles.
imageSmoothArc(resource &$img, int $cx, int $cy, int $w, int $h, array $color, float $start, float $stop)
Parameters
- $img
An image resource, returned by
imagecreatetruecolor()and with enabled alpha-blending and disabled antialiasing- $cx
x-coordinate of the center
- $cy
y-coordinate of the center
- $w
The arc width
- $h
The arc height
- $color
The first three values are RGB components (0-255). The fourth value is the alpha blending factor (0-127). You can use this to create transparency effects.
- $start

The arc's start angle, in radians, not limited to the range 0...2*PI. 0 is located at the three-o'clock position. The arc is drawn counter-clockwise. $start can be greater than $stop
- $stop
The arc's end angle, in radians.
Example
This will draw a yellow half-transparent antialiased elliptical arc.
<?php
include('imageSmoothArc.php');
$img = imageCreateTrueColor(200, 100);
imagealphablending($img, TRUE);
imageantialias($img, FALSE);
imageSmoothArc($img, 100, 50, 180, 80, array(255, 255, 140, 64), M_PI/2, 0);
header('Content-type: image/png');
imagepng($img);
imagedestroy($img);
?>
Additional Information
Wrapper Function
If you prefer degrees over radians or if you do not like counter-clockwise drawing or an array for the color parameter, you can use the wrapper function that Tibor posted in the comments section:
<?php
function imageFilledSmoothArc ($img, $cx, $cy, $width, $height, $startDegree, $stopDegree, $colorId) {
// Added by Tibor, 02/2010
// Wrapper function for users of 'imageFilledArc()' which is a PHP function for GD2
// 'imageFilledArc()':
// * draws from $start to $stop clockwise
// * uses a clockwise coordinate system
// * uses degrees for the angles
// * uses color identifier from imageColorAllocate()
// 'imageSmoothArc':
// * draws from $start to $stop counter-clockwise
// * uses a counter-clockwise coordinate system
// * uses radians for the angles
// * uses an RGBA array for the color
// So if you used:
// imageFilledArc($img, $cx, $cy, $w, $h, 30, 120, $colorId)
// then you should transform the start, stop and color values:
// imageSmoothArc (
$stopRadian = (0 - $startDegree) / 180 * M_PI;
// Transforming $colorIdentifier to $colorRGBA
// 'imageSmoothArc()' requires an array of four RGBA color values ([0]=>255,[1]=>255,[2]=>255,[3]=>0)
// Thefirst three values are the RGB color, the fourth is the alpha blending factor.
// 'imageColorsForIndex()' returns an associative array (["red"]=>255, ["green"]=> 255, ["blue"]=> 255, ["alpha"]=>0)
$colorRGBA = array_values(imageColorsForIndex($img, $colorId));
// Drawing the elliptic arc with imageSmoothArc()
imageSmoothArc($img, $cx, $cy, $width, $height, $colorRGBA, $startRadian, $stopRadian);
}
?>
Drawing Outlined Antialiased Arcs
You can also draw outlined antialiased arcs with a simple trick: Draw an arc with the border color and draw a slightly smaller arc with your background color over it.
Questions?
If you have questions regarding these scripts or if you need help with specific problems, do not hesitate to contact me.
Comments (36)
Comments are temporarily closed. Please contact me if your question is not answered.
Well done.
Well done bro, it looks awesome! Please see into the mail that I sent you, thanks! ;-)
Just awesome!
Very good :)
Tanks,Very good
This technology is BRILLIANT. I have been looking for this exact idea everywhere and would not have been able to do this otherwise. Thank you!
This is brilliant! I'm writing graph library and this very very helpful. I will post a link what it's suitable for a release. Thank you!
Aweome! Thanks so much -- it works great!
dont use "imageantialias($im, true);"
Hello Ulrich,
great utility! Thanks for your efforts.
I have a question: I've been testing the script, and the color of the resulting ellipse's "filling" is not exactly the color I feed as an argument. E.g. if I tell the script to use #993300 the color picker in Gimp says that the resulting ellipse has #9C3204 as background (filling or non antialiased portion's) color.
Interesting. Do you save your images as PNGs or JPEG/Gif?
Sorry for replying a bit late..
Do you save your images as truecolor pngs? Or do you use gif/jpeg or a color palette?
just want to say thanks for your great work. Marvellous ! :-)
I don't understand, but this script only draws 90, 180, 270 and 360 degrees?
opss.well i downloaded the optimized version.
Hi Ulrich,
What a brilliant tool. I am working on a PHP class that will resize/cache and now add rounded (beautiful antialiased) corners to photos.
Will keep you updated; still working on my website :)
Hi Ulrich, it is a great tool.
What should I change if I need to render an elliptical arc in the other direction? (from $stop to $start on your picture, but to the right, so the starting angle of the elliptical arc is ~30 degrees and ending angle is ~120 degrees). I hope it was clear :)
I am not really sure what you would like to do, but you could either use
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 30 / 180.0 * M_PI, 120 / 180.0 * M_PI)
which would draw from 30° to 120° counter-clockwise or
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 120 / 180.0 * M_PI, 30 / 180.0 * M_PI)
which would draw from 30° to 120° clockwise
I would like to draw from 30° to 120° clockwise. It works for me with the example you gave me. However, it draws clockwise with your counter-clockwise example and vice versa. So
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 30 / 180.0 * M_PI, 120 / 180.0 * M_PI)
draws me from 30° to 120° clockwise. And I wanted exactly this :) Thanks a lot!
That is strange. I tested this to be sure, and
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 30 / 180.0 * M_PI, 120 / 180.0 * M_PI)
draws counter-clockwise for me.
Hmmm, I need to correct my previous post: I think both of your examples draw counter-clockwise and this was my original problem.
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 30 / 180.0 * M_PI, 120 / 180.0 * M_PI)
draw from 30° to 120° counter-clockwise and
imageSmoothArc (&$img, $cx, $cy, $w, $h, $color, 120 / 180.0 * M_PI, 30 / 180.0 * M_PI)
draw from 120° to 30° counter-clockwise.
What I am looking for is drawing from 30° to 120° clockwise. Is it possible with imageSmoothArc?
Yes, absolutely. By default, it draws from $start to $stop counter-clockwise. If you swap $start and $stop, it will draw clockwise.
You said, the last example code draws from 120° to 30° counter-clockwise. Isn't this the same as drawing from 30° to 120° clockwise?
I checked more examples and I think I understand what imageSmoothArc does :)
I was confused because I used 'imageFilledArc' before (it is a PHP function for GD2) and it:
- draws from $start to $stop clockwise
- uses a clockwise coordinate system
- uses degrees for the angles
- uses color identifier from imageColorAllocate()
Then I tried your 'imageSmoothArc' which:
- draws from $start to $stop counter-clockwise
- uses a counter-clockwise coordinate system
- uses radians for the angles
- uses an RGBA array for the color
So if I used:
imageFilledArc($img, $cx, $cy, $w, $h, 30, 120, $colorId)
then I need to use:
imageSmoothArc (&$img, $cx, $cy, $w, $h, $colorRGBA, -120 / 180.0 * M_PI, -30 / 180.0 * M_PI)
which produces exactly the same elliptical arc - but renders very nice high quality graphics (note the - sign and the radians).
I hope it helps for others and could be a small Migrating Guide from 'imageFilledArc' to 'imageSmoothArc' :)
You are right, the interface is a bit confusing compared to imagefilledarc.
I should really add some migration documentation (or better: a wrapper)
I put this code into 'imageSmoothArc.php' and I use the 'imageFilledSmoothArc()' function as a wrapper.
function imageFilledSmoothArc ($img, $cx, $cy, $width, $height, $startDegree, $stopDegree, $colorId) {
// Added by Tibor, 02/2010
// Wrapper function for users of 'imageFilledArc()' which is a PHP function for GD2
// 'imageFilledArc()':
// * draws from $start to $stop clockwise
// * uses a clockwise coordinate system
// * uses degrees for the angles
// * uses color identifier from imageColorAllocate()
// 'imageSmoothArc':
// * draws from $start to $stop counter-clockwise
// * uses a counter-clockwise coordinate system
// * uses radians for the angles
// * uses an RGBA array for the color
// So if you used:
// imageFilledArc($img, $cx, $cy, $w, $h, 30, 120, $colorId)
// then you should transform the start, stop and color values:
// imageSmoothArc (&$img, $cx, $cy, $w, $h, $colorRGBA, -120 / 180.0 * M_PI, -30 / 180.0 * M_PI)
// which produces exactly the same elliptical arc - but renders very nice high quality graphics (note the - sign and the radians).
// This wrapper function takes care of the necessary transformations,
// so you can easily migrate your code from:
// imageFilledArc($img, $cx, $cy, $w, $h, 30, 120, $colorId)
// to:
// imageFilledSmoothArc($img, $cx, $cy, $w, $h, 30, 120, $colorId)
// Parameters:
// $cx - Center of ellipse, X-coord
// $cy - Center of ellipse, Y-coord
// $width - Width of ellipse ($w >= 2)
// $height - Height of ellipse ($h >= 2 )
// $startDegree - Starting angle of the arc in degrees, no limited range!
// $stopDegree - Stopping angle of the arc in degrees, no limited range!
// $colorId - Color identifier from imageColorAllocate()
// $start _can_ be greater than $stop!
// Transforming $startDegree and $stopDegree to $startRadian and $stopRadian
// 'imageSmoothArc()' uses a counter-clockwise coordinate system (the coordinates should be negative)
// 'imageSmoothArc()' draws counter-clockwise (therefore $start and $stop should be swapped)
// 'imageSmoothArc()' uses radians for the angles ($radians = $degrees / 180.0 * M_PI)
$startRadian = (0 - $stopDegree) / 180 * M_PI;
$stopRadian = (0 - $startDegree) / 180 * M_PI;
// Transforming $colorIdentifier to $colorRGBA
// 'imageSmoothArc()' requires an array of four RGBA color values ([0]=>255,[1]=>255,[2]=>255,[3]=>0)
// Thefirst three values are the RGB color, the fourth is the alpha blending factor.
// 'imageColorsForIndex()' returns an associative array (["red"]=>255, ["green"]=> 255, ["blue"]=> 255, ["alpha"]=>0)
$colorRGBA = array_values(imageColorsForIndex($img, $colorId));
// Drawing the elliptic arc with imageSmoothArc()
imageSmoothArc($img, $cx, $cy, $width, $height, $colorRGBA, $startRadian, $stopRadian);
}
Thanks for sharing! :)
I think this will help a lot of people to use the script.
Hi,
How do I use Imagesmootharc and the class to draw rounded corners where the shapes have stroke color with alpha and fill color with alpha?
I tried to draw an initial shape (say an ellipse) with and alpha and reduce the width&height based on the required stroke and then drew another ellipse with the fill color and different alpha. The problem is that the fill color gets merged with the stroke color which was drawn first. Can anyone help me with this?
Hari
I think you will have to modify the script a bit, so that it does what you want.
Hi! nice script! Is there any way to draw this anti-aliased arc on a transparent background?
Hi. Yes that should be possible. I think this example should helps you:
<a href="http://www.php.net/manual/en/function.imagecreatetruecolor.php#91180" target="_blank">http://www.php.net/manual/en/function.imagecreate...</a>
But I haven't tried it yet
Hello -
First off, thanks for the wonderful package you've made. Just had a small problem (bug?) with the functions. Below is a small set of test data (assume that your code (non-optimized 1.1, although I've tried it with the optimized and the results are the same) is just below this code )
//Build the frame
$width = 400;
$height = 400;
$im = @imageCreateTrueColor ($width,$height);
imagealphablending ($im, true);
$background_color = imagecolorallocate ($im, 255,255,255); //white background
imageFill($im,0,0,$background_color);
imageSmoothArc ( $im, $width/2, $height/2, $width,$height,array(0,0,0,0),0, 2*M_PI);
imagepng ($im,'test.png');
imagedestroy($im);
echo "<img src='test.png' style='width: 400px; height: 400px'/>";
I've noticed that while the left side rests perfectly against the edge of the image, the top/right/bottom edges of the circle push past the image (you can see them getting clipped). The effect is easier to see if you change width/height to 50px and keep the blown up 400x400px display.
Is this cropping a limitation of the library? It can be 'solved somewhat' by shrinking the height/width of the circle/arc, but then you get an unbalanced image because there is more background space on the left than there is on the right.
Hoping you can help, and thanks in advance! These functions are going to be extremely useful with a fun little Japanese-language tool I'm making.
</img>
Hi,
The problem you are describing is a known error. If you only need full circles (or 90°, 180°, 270°), you can use the optimized version and the modification I described here: <a href="http://mierendo.com/software/rounded_css_boxes/#IDComment15792718" target="_blank">http://mierendo.com/software/rounded_css_boxes/#I...</a>
I hope this helps you.
Can i use this script to round image corners with aliasing?
That is not supported, but you could modify the script (imageSetPixel and imageLine calls).
hanks for the wonderful package you've made.
Ahh, I wish that russian guy would share his code that he used for his 3d pie chart generator.
Very nice.