PDA

View Full Version : anti-aliased lines



peterbone
02-07-2003, 10:04 AM
Has anyone got any code for drawing anti-aliased lines? Preferably quickly using scanline. And I mean a proper anti-aliased line - not just drawing a line and then blurring it.

Thanks

Peter

Alimonster
02-07-2003, 10:20 AM
Would Wu anti-aliasing do you? I know that there's an add-on somewhere at Turbo (http://turbo.gamedev.net/delphix.asp) which implements this (TurboPixels or something like that -- maybe by Michael Wilson). It's for DelphiX but shouldn't be difficult to convert to normal TBitmap. I'm pretty sure that Graphics32 (http://www.g32.org/graphics32/) has anti-aliasing (and incidentally, it's waaay faster at some things than TBitmap/TCanvas -- check the demos) too. Are the above any use to you?

peterbone
02-07-2003, 12:58 PM
Weird, that's exactly what I did! I used the Turbo Pixel code and modified it.
Here's my code.



type
TRGBTripleArray = array[0..1000] of TRGBTriple;
PRGBTripleArray = ^TRGBTripleArray;

// anti-aliased line
procedure TForm1.WuLine(ABitmap : TBitmap ; x1, y1, x2, y2 : Integer ; AColor : TColor);
var
deltax, deltay, loop, start, finish: integer;
dx, dy, dydx: single; // fractional parts
LR, LG, LB : byte;
begin
deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
deltay := abs(y2 - y1);
if (deltax = 0) or (deltay = 0) then begin // straight lines
ABitmap.Canvas.Pen.Color := AColor;
ABitmap.Canvas.MoveTo(x1, y1);
ABitmap.Canvas.LineTo(x2, y2);
exit;
end;
LR := (AColor and $000000FF);
LG := (AColor and $0000FF00) shr 8;
LB := (AColor and $00FF0000) shr 16;
if deltax > deltay then begin // horizontal or vertical
if y2 > y1 then // determine rise and run
dydx := -(deltay / deltax)
else
dydx := deltay / deltax;
if x2 < x1 then begin
start &#58;= x2; // right to left
finish &#58;= x1;
dy &#58;= y2;
end else begin
start &#58;= x1; // left to right
finish &#58;= x2;
dy &#58;= y1;
dydx &#58;= -dydx; // inverse slope
end;
for loop &#58;= start to finish do begin
AlphaBlendPixel&#40;ABitmap, loop, trunc&#40;dy&#41;, LR, LG, LB, 1 - frac&#40;dy&#41;&#41;;
AlphaBlendPixel&#40;ABitmap, loop, trunc&#40;dy&#41; + 1, LR, LG, LB, frac&#40;dy&#41;&#41;;
dy &#58;= dy + dydx; // next point
end;
end else begin
if x2 > x1 then // determine rise and run
dydx &#58;= -&#40;deltax / deltay&#41;
else
dydx &#58;= deltax / deltay;
if y2 < y1 then begin
start &#58;= y2; // right to left
finish &#58;= y1;
dx &#58;= x2;
end else begin
start &#58;= y1; // left to right
finish &#58;= y2;
dx &#58;= x1;
dydx &#58;= -dydx; // inverse slope
end;
for loop &#58;= start to finish do begin
AlphaBlendPixel&#40;ABitmap, trunc&#40;dx&#41;, loop, LR, LG, LB, 1 - frac&#40;dx&#41;&#41;;
AlphaBlendPixel&#40;ABitmap, trunc&#40;dx&#41; + 1, loop, LR, LG, LB, frac&#40;dx&#41;&#41;;
dx &#58;= dx + dydx; // next point
end;
end;
end;

// blend a pixel with the current colour and a specified colour
procedure TForm1.AlphaBlendPixel&#40;ABitmap &#58; TBitmap ; X, Y &#58; integer ; R, G, B &#58; byte ; ARatio &#58; Real&#41;;
Var
LBack, LNew &#58; TRGBTriple;
LMinusRatio &#58; Real;
LScan &#58; PRGBTripleArray;
begin
LScan &#58;= ABitmap.Scanline&#91;Y&#93;;
LMinusRatio &#58;= 1 - ARatio;
LBack &#58;= LScan&#91;X&#93;;
LNew.rgbtBlue &#58;= round&#40;B*ARatio + LBack.rgbtBlue*LMinusRatio&#41;;
LNew.rgbtGreen &#58;= round&#40;G*ARatio + LBack.rgbtGreen*LMinusRatio&#41;;
LNew.rgbtRed &#58;= round&#40;R*ARatio + LBack.rgbtRed*LMinusRatio&#41;;
LScan&#91;X&#93; &#58;= LNew;
end;


Thanks anyway

Peter

Alimonster
02-07-2003, 01:24 PM
I must admit that that procedure doesn't seem very optimised (lots of converting to/from floats... hmm!). Maybe this one (http://www.vclcomponents.com/search.asp?ID_CATEGORY=145&PGIX=18) is a bit better -- I had a quick look and it seems to avoid any floats (good for speed). I haven't tried it, though, since I'm at work. It should be very straightforward for you to use -- just replace the Canvas.Pixels[] lines with the equivalent scanline thing.

EDIT: antialia.zip from that page. Also, I haven't checked that it does arbitrary angles and isn't just up/down/left/right. I hate being at work!

peterbone
02-07-2003, 01:43 PM
That one looks a bit weird to me. I'm not sure it's Wu. I'm happy with the one I've got - it doesn't need to be that fast because I'm just drawing it on a background bitmap so it's only drawn once and not every frame.

Peter