libGD

GD is an open source code library for the dynamic creation of images by programmers. GD is written in C, and “wrappers” are available for Perl, PHP and other languages. GD creates PNG, JPEG and GIF images, among other formats. GD is commonly used to generate charts, graphics, thumbnails, and most anything else, on the fly. While not restricted to use on the web, the most common applications of GD involve web site development.

See the GD website for more informations.

| Tasklist |

FS#79 — arc's are drawn incorrectly (plus regression in 2.0.35RC2)

Attached to Project — libGD
Opened by Colen Garoutte-Carson (Colen) - Friday, 04 May 2007, 09:15 GMT+2
Last edited by Pierre Joye (Pierre) - Thursday, 21 June 2007, 21:39 GMT+2
Task Type Bug Report
Category Drawing function
Status Waiting on Customer
Assigned To Pierre Joye (Pierre)
Operating System All
Severity High
Priority Normal
Reported Version 2.0.34
Due in Version 2.1.0
Due Date Undecided
Percent Complete 0%
Votes 1
Private No

Details

I recently upgraded from 2.0.33 to 2.0.35RC2, to see if some bugs I’ve encountered had been fixed, before reporting them. I noticed a regression in how arc’s are drawn. See the attached images. The left side of the circle generated by 2.0.35RC2 looks corrupted. Since the algorithm should be equivilent in all 4 quadrants, hopefully it’s just a minor math error translating between quandrants.

Another (existing) issue I’ve encountered is that arcs of any significant thickness do not draw correctly. I’ve attached the same circles at a thickness of 50 (though the problem is noticable at a thickness of 3). Neither looks much like a circle.

- Colen

This task depends upon

Comment by Pierre Joye (Pierre) - Friday, 04 May 2007, 09:29 GMT+2
  • Field changed: Status (Unconfirmed → Waiting on Customer)

Hi,

Thanks for your feedback!

The gdImageArc implementation did not change, however I suspect another bug to be the cause of this problem: #77 (http://bugs.libgd.org/?do=details&task_id=77)

vertical lines were not drawn correclty anymore, this regression was introduced after a fix in the anti anti aliased line function (axis aligned lines were two pixels wide).

Please try your code using the CVS version (I will release a RC3 during the weekend). I will also add new test cases regarding the arc functions.

About the thickness problem, it is a general problem with many shapes. I’m working on a solution for gd 2.1.0. See the following samples: http://blog.thepimp.net/misc/ellipsethick.html (ellipse with thickness > 1 and transparency) or http://pierre.libgd.org/polygons/ (general shapes antialiasing, incl. transparency support)

Comment by Colen Garoutte-Carson (Colen) - Saturday, 05 May 2007, 07:21 GMT+2

I'm trying to install the CVS version, but am getting:

aclocal:configure.ac:64: warning: macro `AM_ICONV' not found in library
Makefile.am:18: Libtool library used but `LIBTOOL' is undefined
Makefile.am:18:
Makefile.am:18: The usual way to define `LIBTOOL' is to add `AC_PROG_LIBTOOL'
Makefile.am:18: to `configure.ac' and run `aclocal' and `autoconf' again.
Failed

...on RH Linux ES4. I installed the latest version of autoconf, but this still repros. Do I need to upgrade or downgrade something?

Thanks, - Colen

Comment by Pierre Joye (Pierre) - Saturday, 05 May 2007, 09:49 GMT+2
...on RH Linux ES4. I installed the latest version of autoconf, but this still repros. Do I need to upgrade or downgrade something?

You may need a more recent autoconf version. I know automake 1.9 is required, I'm not sure about the minimum version of autoconf. I use 2.61.

You can setup it in a separate directory and override the default using:

AUTOCONF=/home/colen/usr/bin/autoconf

for example. AUTOCONF, ACLOCAL, AUTOHEADER and AUTOMAKE can be set.

Comment by Pierre Joye (Pierre) - Saturday, 05 May 2007, 09:55 GMT+2

I forgot to mention the branch to use. Please use GD_2_0 (cvs -r GD_20...)

Comment by Pierre Joye (Pierre) - Saturday, 05 May 2007, 09:55 GMT+2

I forgot to mention the branch to use. Please use GD_2_0 (cvs -r GD_2_0...)

Comment by Colen Garoutte-Carson (Colen) - Saturday, 05 May 2007, 10:43 GMT+2

I have autoconf 2.61 and automake 1.9.6 installed. I tried automake 1.9, as you suggested. I also tried with and without "-r GD_2_0". In each case, I got the same output from bootstrap.sh . Example is attached. I appologize if this is due to an issue on my system. (Unix is not my native platform.) But, it sounds like you have solutions for both arc issues. I look forward to version 2.1. :)

Comment by Pierre Joye (Pierre) - Sunday, 06 May 2007, 23:05 GMT+2

I uploaded 2.0.35RC3, it may help you to test the last changes.

You can find it here: http://www.libgd.org/releases/

Please let me know if it works as expected (except the thickness problem, that's another issue for 2.1.0)

Comment by Colen Garoutte-Carson (Colen) - Monday, 07 May 2007, 07:13 GMT+2

I was able to fix my config problem. I needed to update libtool.

2.0.35RC3 seems to address the problem for gif and jpeg, but I am seeing a problem with anti-aliased lines and arcs in PNG TrueColor images.

$im = new GD::Image($width, $height, 1);
...
$im->fill(0,0,$white);
$im->setThickness(3);
$im->setAntiAliased($black);
$im->arc($x1, $y1, $x2, $y2, 0, 360, gdAntiAliased);
...
print "Content-type: image/png\n\n";
print $im->png;

... generates the attached image. Similar artifacts are there, and the thickness is not correct. The problem does not happen if gdAntiAliased is not used.

- Colen

Comment by Pierre Joye (Pierre) - Monday, 07 May 2007, 09:00 GMT+2
The problem does not happen if gdAntiAliased is not used.

Ok, the antialias multiple blending ends with a horrible result in gdImageArc and without any antialiasing effect (still jaggy anyway).

The attached patch fixes the issue. I think it is a good way to solve the problem without loosing the actual fix in gdImageAALine for axis aligned lines.

The previous versions did not draw arcs pixels using only black. I think it is an acceptable change given that it never works well anyway. Is it good enough in your case?

Comment by Colen Garoutte-Carson (Colen) - Monday, 07 May 2007, 10:42 GMT+2

I am seeing the problem with AA lines as well. AA lines at certain angles(?) are not drawn in true-color PNG. (Attached is a circle drawn using lines.) I'd like to use PNG output to support alpha anti-aliased text, which works well. Is there a existing solution for drawing smooth/AA diagonal lines in true-color PNG?

- Colen

   test.png (62.8 KiB)
Comment by Pierre Joye (Pierre) - Monday, 07 May 2007, 11:07 GMT+2
I am seeing the problem with AA lines as well. AA lines at certain angles(?) are not drawn in true-color PNG. (Attached is a circle drawn using lines.) I'd like to use PNG output to support alpha anti-aliased text, which works well.

It is not a problem of the AA lines but the way we draw circles, ellipses (arc or full). We draw arcs using many lines. Extrems of the arc are drawn using single pixel lines mostl. Many of them overlap, blending ops are done many times within the same area. It ends to pure white when the drawing operation is finished.

Is there a existing solution for drawing smooth/AA diagonal lines in true-color PNG?

You can draw AA lines at any angle, it works. But if you draw again again on the same area, the result will likely look like the background color.

A better approach to draw circles or ellipses is to use the Bresenham algorithm. I use it in my new implementation of the gdImageFilledEllipse function (already in 2.0.34 and later). That's what I use as well in the upcoming antialiased arcs functions.

What's about this change, does it work as you expect? (without AA, it cannot be done in 2.0.x but in 2.1.x).

Comment by Pierre Joye (Pierre) - Monday, 07 May 2007, 11:34 GMT+2

I made a mistake in my comment. Your image is relatively very large and reduce the effect I was trying to describe. There is (bad) regression here. A fix will be present in 2.0.35 (meaning a RC4, damned :).

Thanks for your patience!

Comment by Pierre Joye (Pierre) - Monday, 07 May 2007, 12:28 GMT+2

Fixed in GD_2_0 and HEAD. It should work as you expect now. The fix will be in 2.0.35.

Comment by Colen Garoutte-Carson (Colen) - Monday, 07 May 2007, 21:42 GMT+2

Cool. :) To clarify, "test.png" was not drawn using arcs. I drew that circle with lines, by rotating individual points and connecting them.

- Colen

Comment by Pierre Joye (Pierre) - Tuesday, 08 May 2007, 01:12 GMT+2

"Cool. :) To clarify, "test.png" was not drawn using arcs. I drew that circle with lines, by rotating individual points and connecting them."

Yes, I saw it afterwards, we use a similar implementation in the current arc function.

Only to be sure that everything works well, can you try again using CVS (GD_2_0 or head) please?

Comment by Colen Garoutte-Carson (Colen) - Tuesday, 08 May 2007, 05:59 GMT+2

There are still problems with the latest from CVS. Diagonal lines use incorrect width and are antialiased against the wrong color (black instead of transparent?).

Attached is the same circle made w/lines, at thickness of 6, anti-aliased against transparent (0,0,0,127).

The same drawing operations look correct when not using truecolor png, or when saveAlpha is 0.

- Colen

Comment by Pierre Joye (Pierre) - Tuesday, 08 May 2007, 10:17 GMT+2

"There are still problems with the latest from CVS. Diagonal lines use incorrect width and are antialiased against the wrong color (black instead of transparent?)."

Do you mean when the thickness > 1? Antialiased lines do not support thickness > 1, it is always 1. If not and if the wrong color still appears, do you have a sample code and result (only the line)? I cannot reproduce the problem here. 45° line are not really antialiased are they are pixel aligned, each point of the lines cover a complete pixel (end points are always on a pixel):

[X]
   [X]
      [X]

Maybe it is what you are seeing?

"Attached is the same circle made w/lines, at thickness of 6, anti-aliased against transparent (0,0,0,127). The same drawing operations look correct when not using truecolor png, or when saveAlpha is 0. "

Thickness does not work, it will only work correctly in 2.1.0. When the thickness>1, it will draws many times the same spans (blending over and over the same pixels).

Am I right to think that it actually works for you now (like with 2.0.33)? :)

The improvements (thickness>1 and transparency) will be done later, in the 2.1.x branch.

Comment by Colen Garoutte-Carson (Colen) - Wednesday, 09 May 2007, 05:44 GMT+2
$im = new GD::Image($width, $height, 1);
$im->alphaBlending(0);
$im->saveAlpha(1);
$transparent = $im->colorAllocateAlpha(0,0,0,127);
$im->fill(0,0,$transparent);
$im->setAntiAliased($red);
$im->setThickness(6);
@prevpts = ( $center, $center + $radius );
for ($i=0;$i<=360;$i++)
{
	@newpts = &RotatePointAroundOrigin($center, $center, $center, $center + $radius, $i);
	$im->line($prevpts[0], $prevpts[1], $newpts[0], $newpts[1], gdAntiAliased);
	@prevpts = @newpts;
}

This is what I used to generate test2.png. I see the same affect with arcs, but this demonstrates that lines are affected as well. When output to a PNG image, there are 2 problems:

1) The lines are anti-aliased against the wrong background color. If you view the image over a white background, you will see that the lines were anti-aliased against black (instead of anti-aliased using alpha, such as text rendered by stringFT would be). If you set the thickness to 1, you will see the same problem. This is a problem with anti-aliased lines (with thickness==1) and alpha transparency, and is not related to thickness >1 or arc's.

2) Angled lines are rendered differently than horizontal and vertical lines. In some conditions, you are are using the requested thickness and not anti-aliasing. In other conditions, you are anti-aliasing, but reducing the thickness to 1. Since my drawning code is independant of the output format, my suggestion would be to always disable anti-aliasing and use the requested thickness, when thickness >1 is requested. That would be the closest to the desired effect, and would make the image look more consistent across output formats.

- Colen

Comment by Pierre Joye (Pierre) - Wednesday, 09 May 2007, 09:01 GMT+2

"This is what I used to generate test2.png. I see the same affect with arcs, but this demonstrates that lines are affected as well. When output to a PNG image, there are 2 problems:"

For clarity, there is only two buffer formats:

  • TrueColor 8 bits per channel and 7 bit for alpha, the color values are stored directly in the image
  • Palette image, 8 bits per channel and 7 bit for alpha, the color values are stored in a palette and only the index is stored in the image. Limited to 256 colors (bgd incl.)

Each of this format can be saved to an image file or stream. Internally each file format support both or only one image type. PNG supports both, GIF supports only palette based image (we have to use dithering for truecolor iamge), jpeg support only truecolor image.

"The lines are anti-aliased against the wrong background color. If you view the image over a white background, you will see that the lines were anti-aliased against black (instead of anti-aliased using alpha, such as text rendered by stringFT would be)."

That's yet another problem. We do not support AA based on the alpha channel like what we do in the StringFT functions. By the way, it does not happen with a white background but when the backroung is completely transparent (gdTrueColorAlpha(0,0,0,127) in your example).

"Angled lines are rendered differently than horizontal and vertical lines. In some conditions, you are are using the requested thickness and not anti-aliasing."

The start and end of each line are pixel aligned (no partial coverage). There is no AA for axis aligned lines as they fit exactly on the pixels they cover. For a non axis aligned line, the ideal line (with a thickness of 1) will cover more than one pixel, for example 80% at (10,10) and 20% at (10,11) is the position for the pixel at (10.0, 10.20).

"my suggestion would be to always disable anti-aliasing and use the requested thickness, when thickness >1 is requested. That would be the closest to the desired effect, and would make the image look more consistent across output formats."

It sadly cannot be done now as it will suddenly bring some backward compatibility problem. I suggest you to manually disable AA when you have a thickness > 1. Doing so will help you to implement a function compatible with 2.1.0 and earlier version as well.

To bring at least one good news, 2.1.0 may support floating start/end points. It will greatly improve the complex shapes rendering and positioning.

I would you like to thank you again for the detailed feedbacks. It confirms the choices we made for 2.1.0 and gave us a couple of good test cases!

I will close this bug as the initial issue is fixed and the other problems described here are already reported in other bug reports (AA, arcs and lines with thickness and alpha values).

Comment by Pierre Joye (Pierre) - Thursday, 21 June 2007, 21:39 GMT+2
  • Field changed: Due in Version (2.0.35 → 2.1.0)

Initial problem is fixed in 2.0.35. Move it to 2.1.0 until a separate issue has been created for the other problem described here.

Loading...