Draw an antialiased line (Views: 29)
Problem/Question/Abstract: How to draw an antialiased line Answer: Here's a procedure that uses a modified version of Gupta-Sproull anti-aliasing: procedure DrawLine(Canvas: TCanvas; x1, y1, x2, y2: integer); procedure DrawPixel(x, y: integer; Distance: double); var Alpha: integer; begin Alpha := 255 - Trunc(255 * Sqr(1 - Distance * 2 / 3)); Canvas.Pixels[x, y] := Alpha or (Alpha shl 8) or (Alpha shl 16); end; var i, deltax, deltay, numpixels, d, dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2: Integer; du: Integer; twovdu: Integer; invD: Double; invD2du: Double; vincx, vincy: Integer; begin {Calculate deltax and deltay for initialisation} deltax := abs(x2 - x1); deltay := abs(y2 - y1); {Initialize all vars based on which is the independent variable} if deltax >= deltay then begin {x is independent variable} numpixels := deltax + 1; d := (2 * deltay) - deltax; dinc1 := deltay shl 1; dinc2 := (deltay - deltax) shl 1; xinc1 := 1; xinc2 := 1; yinc1 := 0; yinc2 := 1; du := deltax; vincx := 0; vincy := 1; end else begin {y is independent variable} numpixels := deltay + 1; d := (2 * deltax) - deltay; dinc1 := deltax shl 1; dinc2 := (deltax - deltay) shl 1; xinc1 := 0; xinc2 := 1; yinc1 := 1; yinc2 := 1; du := deltay; vincx := 1; vincy := 0; end; twovdu := 0; invD := 1 / (2 * sqrt(deltax * deltax + deltay * deltay)); invD2du := 2 * (du * invD); {Make sure x and y move in the right directions} if x1 > x2 then begin xinc1 := -xinc1; xinc2 := -xinc2; vincx := -vincx; end; if y1 > y2 then begin yinc1 := -yinc1; yinc2 := -yinc2; vincy := -vincy; end; {Start drawing at [x1, y1]} x := x1; y := y1; {Draw the pixels} for i := 1 to numpixels do begin DrawPixel(x, y, twovdu * invD); DrawPixel(x + vincx, y + vincy, invD2du - twovdu * invD); DrawPixel(x - vincx, y - vincy, invD2du + twovdu * invD); if d < 0 then begin twovdu := d + du; d := d + dinc1; x := x + xinc1; y := y + yinc1; end else begin twovdu := d - du; d := d + dinc2; x := x + xinc2; y := y + yinc2; end; end; end; |