edrad's pseudo-sphere is pretty nice, but a few tweeks really improve it. (writing out the image header so a browser actually understands it and calling imagedestroy() so we clean up memory are nice things to do, too). Try drawing it at twice the size and then resampling it down. Takes more CPU, but it forces antialiasing, creating a smooth arc. Also, render it at diameter = (width - 1) * 2. Taking one pixel off the outside keeps it off the image edge, eliminating those ugly flat spots. Render it on white first so you can really see the edge, then switch back to the cool grey...
Oh, and use imagecreatetruecolor instead of imagecreate if you have it available.
I agree that imageellipse is easier, though. Actually, I generate rounded corners with drop-shadows for CSS with imagefilledarc (kind of a blend of the two) Use imagefilledellipse if drawing the whole thing, use imagefilledarc if only drawing part of it (like a corner). If you use the 'filled' functions you can skip imagefilltoborder altogether :P
Anyway, try this for a smoother image:
<?php
$requested_width = 300;
$render_width = ($requested_width * 2) - 1; $center = $render_width / 2;
$colordivs = 255 / $center;
$im_scratch = @imagecreate($render_width, $render_width);
$back_color = imagecolorallocate($im_scratch, 255, 255, 255);
imagefill($im_scratch, 0, 0, $back_color);
for ($i = 0; $i <= $center; $i++) {
$diametre = $render_width - 2 * $i;
$el_color = imagecolorallocate($im_scratch, $i * $colordivs, 0, 0);
imageellipse($im_scratch, $center, $center, $diametre, $diametre, $el_color);
imagefilltoborder($im_scratch, $center, $center, $el_color, $el_color);
}
$im = @imagecreatetruecolor($requested_width, $requested_width);
imagecopyresampled($im, $im_scratch, 0, 0, 0, 0, $requested_width, $requested_width, $render_width, $render_width);
header ("Content-type: image/png");
imagepng($im);
ImageDestroy($im);
ImageDestroy($im_scratch);
?>