note 95471 deleted from function.imageantialias by danbrown
| From: | danbrown@php.net | Date: | Mon, 04 Jan 2010 20:53:45 +0000 |
| Subject: | note 95471 deleted from function.imageantialias by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-164640@lists.php.net to get a copy of this message | ||
Note Submitter: verdy_p at wanadoo dot fr
----
Why do you need to use slow irrational floatting point functions (sqrt and pow) to perform this test
?:
if ( sqrt(pow($rxx, 2) + pow($ryy, 2)) < $r ) ...;
Instead, precompute (outside the loop): $r2 = $r * $r;
then use: if ($rxx*$rxx+$ryy*$ryy < $r2) ...;
This is so evident...
Note that there also exists a Bresenham algorithm (using midpoint incrementally and ONLY integers)
for drawing circles, and antoaliasiing can be performed by drawing first within a 16x16 boolean
matrix for subsampling pixels (for each fill pixel position) and counting pixels that are set in
this matrix (with this count, you'll get an antialiasing alpha value between 0 and 256 that you
can normalize to 0..255 by just decrementing it if it's larger then or equal to 128, and you
could directly draw the soid color if this final count is 255, or skip the pixel if this alpha value
is zero, instead of merging the fill color with the fill color according to this computed alpha
shade).
Note also that most fast antialisers use a simple 4x4 subsampling matrix, so they get an alpha
counter in 0..16 that can also be used directly without even normalizing it:
pixel[x,y] = (pixel[x,y]*(16-alphacounter) + fillcolor*alphacounter) >> 4;
If you used a 8x8 subsampling matrix (containing 256 positions) the formula when using the
unnormalized alphacounter would be simply:
pixel[x,y] = (pixel[x,y]*(256-alphacounter) + fillcolor*alphacounter) >> 8;
Of course, after drawing each pixel, you have to clear the subsampling matrix, but you can also make
it faster by detecting the cases where subsampling is needed (only near the border of the circle, at
a radius +/- 0.5) : here again instead of using the radius value, used use the suared radius, in
which case the limits for x^2+y^2 that may need subsampling will just be between:
r2max = (r+1/2)^2 = (r + 1)*r + 1/4
r2min = (r-1/2)^2 = (r - 1)*r + 1/4
Here also you can avoid floating points : instead of comparing squared distance from circle center,
compare four times the squared distance for the tested pixel at (x,y) from circle center: r2t4 =
(x*x+y*y)<<4
and compare it with:
r2t4max = (((r +1)*r)<<2)+1
r2t4min = (((r - 1)*r)<<2)+1
- if r2t4 > r2t4max, the tested pixel is fully outside the circle and needs not be drawn
- if t2t4 < r2t4min, the tested mixel is fully inside the circle and just needs to be drawn with
the plain fill color.
- otherwise using pixel subsampling as above...