Antialiased line drawer using scanline (Views: 29)
Problem/Question/Abstract: How to draw antialiased lines using a TBitmap's scanlines Answer: procedure AALine(x1, y1, x2, y2: single; color: tcolor; bitmap: tbitmap); function CrossFadeColor(FromColor, ToColor: TColor; Rate: Single): TColor; var r, g, b: byte; begin r := Round(GetRValue(FromColor) * Rate + GetRValue(ToColor) * (1 - Rate)); g := Round(GetGValue(FromColor) * Rate + GetGValue(ToColor) * (1 - Rate)); b := Round(GetBValue(FromColor) * Rate + GetBValue(ToColor) * (1 - Rate)); Result := RGB(b, g, r); end; type intarray = array[0..1] of integer; pintarray = ^intarray; procedure hpixel(x: single; y: integer); var FadeRate: single; begin FadeRate := x - trunc(x); with bitmap do begin if (x >= 0) and (y >= 0) and (height > y) and (width > x) then pintarray(bitmap.ScanLine[y])[trunc(x)] := CrossFadeColor(Color, pintarray(bitmap.ScanLine[y])[trunc(x)], 1 - FadeRate); if (trunc(x) + 1 >= 0) and (y >= 0) and (height > y) and (width > trunc(x) + 1) then pintarray(bitmap.ScanLine[y])[trunc(x) + 1] := CrossFadeColor(Color, pintarray(bitmap.ScanLine[y])[trunc(x) + 1], FadeRate); end; end; procedure vpixel(x: integer; y: single); var FadeRate: single; begin FadeRate := y - trunc(y); with bitmap do begin if (x >= 0) and (trunc(y) >= 0) and (height > trunc(y)) and (width > x) then pintarray(bitmap.ScanLine[trunc(y)])[x] := CrossFadeColor(Color, pintarray(bitmap.ScanLine[trunc(y)])[x], 1 - FadeRate); if (x >= 0) and (trunc(y) + 1 >= 0) and (height > trunc(y) + 1) and (width > x) then pintarray(bitmap.ScanLine[trunc(y) + 1])[x] := CrossFadeColor(Color, pintarray(bitmap.ScanLine[trunc(y) + 1])[x], FadeRate); end; end; var i: integer; ly, lx, currentx, currenty, deltax, deltay, l, skipl: single; begin if (x1 <> x2) or (y1 <> y2) then begin bitmap.PixelFormat := pf32Bit; currentx := x1; currenty := y1; lx := abs(x2 - x1); ly := abs(y2 - y1); if lx > ly then begin l := trunc(lx); deltay := (y2 - y1) / l; if x1 > x2 then begin deltax := -1; skipl := (currentx - trunc(currentx)); end else begin deltax := 1; skipl := 1 - (currentx - trunc(currentx)); end; end else begin l := trunc(ly); deltax := (x2 - x1) / l; if y1 > y2 then begin deltay := -1; skipl := (currenty - trunc(currenty)); end else begin deltay := 1; skipl := 1 - (currenty - trunc(currenty)); end; end; currentx := currentx + deltax * skipl; currenty := currenty + deltay * skipl; {} for i := 1 to trunc(l) do begin if lx > ly then vpixel(trunc(currentx), currenty) else hpixel(currentx, trunc(currenty)); currentx := currentx + deltax; currenty := currenty + deltay; end; end; end; |