Table of Contents

Please enable javascript to display TOC.

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.

$startExplanation of $start and $stop angle

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)

  1. Martin on 02 May 2009

    Well done.

  2. Marcus de Vries on 05 Jul 2009

    Well done bro, it looks awesome! Please see into the mail that I sent you, thanks! ;-)

  3. Alex on 08 Jul 2009

    Just awesome!
    Very good :)

  4. reza on 23 Jul 2009

    Tanks,Very good

  5. Mark on 03 Aug 2009

    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!

  6. Martin on 24 Sep 2009

    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!

  7. Markis on 17 Oct 2009

    Aweome!  Thanks so much -- it works great!

  8. qeos on 05 Nov 2009

    dont use "imageantialias($im, true);"

  9. BCzerny on 08 Nov 2009

    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.

    1. Ulrich Mierendorff on 09 Nov 2009

      Interesting. Do you save your images as PNGs or JPEG/Gif?

    2. Ulrich Mierendorff on 17 Dec 2009

      Sorry for replying a bit late..
      Do you save your images as truecolor pngs? Or do you use gif/jpeg or a color palette?

  10. FrenchGuy on 02 Dec 2009

    just want to say thanks for your great work. Marvellous !  :-)

  11. neobie on 28 Dec 2009

    I don't understand, but this script only draws 90, 180, 270 and 360 degrees?

    1. neobie on 28 Dec 2009

      opss.well i downloaded the optimized version.

  12. Alex on 31 Dec 2009

    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 :)

  13. Tibor on 08 Feb 2010

    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 :)

    1. Ulrich Mierendorff on 08 Feb 2010

      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

      1. Tibor on 08 Feb 2010

        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!

        1. Ulrich Mierendorff on 08 Feb 2010

          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.

        2. Tibor on 08 Feb 2010

          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?

          1. Ulrich Mierendorff on 08 Feb 2010

            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?

            1. Tibor on 08 Feb 2010

              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' :)

              1. Ulrich Mierendorff on 08 Feb 2010

                You are right, the interface is a bit confusing compared to imagefilledarc.
                I should really add some migration documentation (or better: a wrapper)

  14. Tibor on 10 Feb 2010

    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);
    }

    1. Ulrich Mierendorff on 10 Feb 2010

      Thanks for sharing! :)
      I think this will help a lot of people to use the script.

  15. Hari on 03 Mar 2010

    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

    1. Ulrich Mierendorff on 03 Mar 2010

      I think you will have to modify the script a bit, so that it does what you want.

  16. illimar on 29 Mar 2010

    Hi! nice script! Is there any way to draw this anti-aliased arc on a transparent background?

    1. Ulrich Mierendorff on 31 Mar 2010

      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

  17. molesquirrel on 14 Apr 2010

    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>

    1. Ulrich Mierendorff on 18 Apr 2010

      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.

  18. lukas on 16 Apr 2010

    Can i use this script to round image corners with aliasing?

    1. Ulrich Mierendorff on 18 Apr 2010

      That is not supported, but you could modify the script (imageSetPixel and imageLine calls).

  19. find store sales on 13 May 2010

    hanks for the wonderful package you've made.

  20. Neddy on 28 Jan 2011

    Ahh, I wish that russian guy would share his code that he used for his 3d pie chart generator.

  21. Smart on 07 May 2011

    Very nice.

Comments are temporarily closed. Please contact me if your question is not answered.