all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

View file

@ -0,0 +1 @@
Implement the [[wp:Xiaolin Wu's line algorithm|Xiaolin Wu's line algorithm]] as described in Wikipedia. This algorithm draw antialiased lines. See [[Bresenham's line algorithm]] for ''aliased'' lines.

View file

@ -0,0 +1,4 @@
---
category:
- Graphics algorithms
note: Raster graphics operations

View file

@ -0,0 +1,54 @@
PROCdrawAntiAliasedLine(100, 100, 600, 400, 0, 0, 0)
END
DEF PROCdrawAntiAliasedLine(x1, y1, x2, y2, r%, g%, b%)
LOCAL dx, dy, xend, yend, grad, yf, xgap, ix1%, iy1%, ix2%, iy2%, x%
dx = x2 - x1
dy = y2 - y1
IF ABS(dx) < ABS(dy) THEN
SWAP x1, y1
SWAP x2, y2
SWAP dx, dy
ENDIF
IF x2 < x1 THEN
SWAP x1, x2
SWAP y1, y2
ENDIF
grad = dy / dx
xend = INT(x1 + 0.5)
yend = y1 + grad * (xend - x1)
xgap = xend + 0.5 - x1
ix1% = xend
iy1% = INT(yend)
PROCplot(ix1%, iy1%, r%, b%, g%, (INT(yend) + 1 - yend) * xgap)
PROCplot(ix1%, iy1% + 1, r%, b%, g%, (yend - INT(yend)) * xgap)
yf = yend + grad
xend = INT(x2 + 0.5)
yend = y2 + grad * (xend - x2)
xgap = x2 + 0.5 - xend
ix2% = xend
iy2% = INT(yend)
PROCplot(ix2%, iy2%, r%, b%, g%, (INT(yend) + 1 - yend) * xgap)
PROCplot(ix2%, iy2% + 1, r%, b%, g%, (yend - INT(yend)) * xgap)
FOR x% = ix1% + 1 TO ix2% - 1
PROCplot(x%, INT(yf), r%, b%, g%, INT(yf) + 1 - yf)
PROCplot(x%, INT(yf) + 1, r%, b%, g%, yf - INT(yf))
yf += grad
NEXT
ENDPROC
DEF PROCplot(X%, Y%, R%, G%, B%, a)
LOCAL C%
C% = TINT(X%*2,Y%*2)
COLOUR 1, R%*a + (C% AND 255)*(1-a), \
\ G%*a + (C% >> 8 AND 255)*(1-a), \
\ B%*a + (C% >> 16 AND 255)*(1-a)
GCOL 1
LINE X%*2, Y%*2, X%*2, Y%*2
ENDPROC

View file

@ -0,0 +1,7 @@
void draw_line_antialias(
image img,
unsigned int x0, unsigned int y0,
unsigned int x1, unsigned int y1,
color_component r,
color_component g,
color_component b );

View file

@ -0,0 +1,103 @@
inline void _dla_changebrightness(rgb_color_p from,
rgb_color_p to, float br)
{
if ( br > 1.0 ) br = 1.0;
/* linear... Maybe something more complex could give better look */
to->red = br * (float)from->red;
to->green = br * (float)from->green;
to->blue = br * (float)from->blue;
}
#define plot_(X,Y,D) do{ rgb_color f_; \
f_.red = r; f_.green = g; f_.blue = b; \
_dla_plot(img, (X), (Y), &f_, (D)) ; }while(0)
inline void _dla_plot(image img, int x, int y, rgb_color_p col, float br)
{
rgb_color oc;
_dla_changebrightness(col, &oc, br);
put_pixel_clip(img, x, y, oc.red, oc.green, oc.blue);
}
#define ipart_(X) ((int)(X))
#define round_(X) ((int)(((double)(X))+0.5))
#define fpart_(X) (((double)(X))-(double)ipart_(X))
#define rfpart_(X) (1.0-fpart_(X))
#define swap_(a, b) do{ __typeof__(a) tmp; tmp = a; a = b; b = tmp; }while(0)
void draw_line_antialias(
image img,
unsigned int x1, unsigned int y1,
unsigned int x2, unsigned int y2,
color_component r,
color_component g,
color_component b )
{
double dx = (double)x2 - (double)x1;
double dy = (double)y2 - (double)y1;
if ( fabs(dx) > fabs(dy) ) {
if ( x2 < x1 ) {
swap_(x1, x2);
swap_(y1, y2);
}
double gradient = dy / dx;
double xend = round_(x1);
double yend = y1 + gradient*(xend - x1);
double xgap = rfpart_(x1 + 0.5);
int xpxl1 = xend;
int ypxl1 = ipart_(yend);
plot_(xpxl1, ypxl1, rfpart_(yend)*xgap);
plot_(xpxl1, ypxl1+1, fpart_(yend)*xgap);
double intery = yend + gradient;
xend = round_(x2);
yend = y2 + gradient*(xend - x2);
xgap = fpart_(x2+0.5);
int xpxl2 = xend;
int ypxl2 = ipart_(yend);
plot_(xpxl2, ypxl2, rfpart_(yend) * xgap);
plot_(xpxl2, ypxl2 + 1, fpart_(yend) * xgap);
int x;
for(x=xpxl1+1; x <= (xpxl2-1); x++) {
plot_(x, ipart_(intery), rfpart_(intery));
plot_(x, ipart_(intery) + 1, fpart_(intery));
intery += gradient;
}
} else {
if ( y2 < y1 ) {
swap_(x1, x2);
swap_(y1, y2);
}
double gradient = dx / dy;
double yend = round_(y1);
double xend = x1 + gradient*(yend - y1);
double ygap = rfpart_(y1 + 0.5);
int ypxl1 = yend;
int xpxl1 = ipart_(xend);
plot_(xpxl1, ypxl1, rfpart_(xend)*ygap);
plot_(xpxl1, ypxl1+1, fpart_(xend)*ygap);
double interx = xend + gradient;
yend = round_(y2);
xend = x2 + gradient*(yend - y2);
ygap = fpart_(y2+0.5);
int ypxl2 = yend;
int xpxl2 = ipart_(xend);
plot_(xpxl2, ypxl2, rfpart_(xend) * ygap);
plot_(xpxl2, ypxl2 + 1, fpart_(xend) * ygap);
int y;
for(y=ypxl1+1; y <= (ypxl2-1); y++) {
plot_(ipart_(interx), y, rfpart_(interx));
plot_(ipart_(interx) + 1, y, fpart_(interx));
interx += gradient;
}
}
}
#undef swap_
#undef plot_
#undef ipart_
#undef fpart_
#undef round_
#undef rfpart_

View file

@ -0,0 +1,103 @@
import std.math, std.algorithm, grayscale_image;
/// Plots anti-aliased line by Xiaolin Wu's line algorithm.
void aaLine(Color)(ref Image!Color img, double x1, double y1,
double x2, double y2,
in Color color)
/*pure*/ nothrow {
// Straight translation of Wikipedia pseudocode.
static double round(in double x) /*pure*/ nothrow {
return floor(x + 0.5); // Not pure.
}
static double fpart(in double x) /*pure*/ nothrow {
return x - floor(x);
}
static double rfpart(in double x) /*pure*/ nothrow {
return 1 - fpart(x);
}
auto dx = x2 - x1;
auto dy = y2 - y1;
immutable ax = abs(dx);
immutable ay = abs(dy);
static Color mixColors(in Color c1, in Color c2, in double p)
pure nothrow {
static if (is(Color == RGB))
return Color(cast(ubyte)(c1.r * p + c2.r * (1 - p)),
cast(ubyte)(c1.g * p + c2.g * (1 - p)),
cast(ubyte)(c1.b * p + c2.b * (1 - p)));
else
// This doesn't work for every kind of Color.
return Color(cast(ubyte)(c1 * p + c2 * (1 - p)));
}
// Plot function set here to handle the two cases of slope.
void delegate(in int, in int, in double) nothrow plot;
if (ax < ay) {
swap(x1, y1);
swap(x2, y2);
swap(dx, dy);
plot = (x, y, p) {
assert(p >= 0.0 && p <= 1.0);
img[y, x] = mixColors(color, img[y, x], p);
};
} else {
plot = (x, y, p) {
assert(p >= 0.0 && p <= 1.0);
img[x, y] = mixColors(color, img[x, y], p);
};
}
if (x2 < x1) {
swap(x1, x2);
swap(y1, y2);
}
immutable gradient = dy / dx;
// Handle first endpoint.
auto xEnd = round(x1);
auto yEnd = y1 + gradient * (xEnd - x1);
auto xGap = rfpart(x1 + 0.5);
// This will be used in the main loop.
immutable xpxl1 = cast(int)xEnd;
immutable ypxl1 = cast(int)floor(yEnd);
plot(xpxl1, ypxl1, rfpart(yEnd) * xGap);
plot(xpxl1, ypxl1 + 1, fpart(yEnd) * xGap);
// First y-intersection for the main loop.
auto yInter = yEnd + gradient;
// Handle second endpoint.
xEnd = round(x2);
yEnd = y2 + gradient * (xEnd - x2);
xGap = fpart(x2 + 0.5);
// This will be used in the main loop.
immutable xpxl2 = cast(int)xEnd;
immutable ypxl2 = cast(int)floor(yEnd);
plot(xpxl2, ypxl2, rfpart(yEnd) * xGap);
plot(xpxl2, ypxl2 + 1, fpart(yEnd) * xGap);
// Main loop.
foreach (immutable x; xpxl1 + 1 .. xpxl2) {
plot(x, cast(int)floor(yInter), rfpart(yInter));
plot(x, cast(int)floor(yInter) + 1, fpart(yInter));
yInter += gradient;
}
}
void main() {
auto im1 = new Image!Gray(400, 300);
im1.clear(Gray.white);
im1.aaLine(7.4, 12.3, 307, 122.5, Gray.black);
im1.aaLine(177.4, 12.3, 127, 222.5, Gray.black);
im1.savePGM("xiaolin_lines1.pgm");
auto im2 = new Image!RGB(400, 300);
im2.clear(RGB(0, 255, 0));
immutable red = RGB(255, 0, 0);
im2.aaLine(7.4, 12.3, 307, 122.5, red);
im2.aaLine(177.4, 12.3, 127, 222.5, red);
im2.savePPM6("xiaolin_lines2.ppm");
}

View file

@ -0,0 +1,79 @@
package raster
import "math"
func ipart(x float64) float64 {
return math.Floor(x)
}
func round(x float64) float64 {
return ipart(x + .5)
}
func fpart(x float64) float64 {
return x - ipart(x)
}
func rfpart(x float64) float64 {
return 1 - fpart(x)
}
// AaLine plots anti-aliased line by Xiaolin Wu's line algorithm.
func (g *Grmap) AaLine(x1, y1, x2, y2 float64) {
// straight translation of WP pseudocode
dx := x2 - x1
dy := y2 - y1
ax := dx
if ax < 0 {
ax = -ax
}
ay := dy
if ay < 0 {
ay = -ay
}
// plot function set here to handle the two cases of slope
var plot func(int, int, float64)
if ax < ay {
x1, y1 = y1, x1
x2, y2 = y2, x2
dx, dy = dy, dx
plot = func(x, y int, c float64) {
g.SetPx(y, x, uint16(c*math.MaxUint16))
}
} else {
plot = func(x, y int, c float64) {
g.SetPx(x, y, uint16(c*math.MaxUint16))
}
}
if x2 < x1 {
x1, x2 = x2, x1
y1, y2 = y2, y1
}
gradient := dy / dx
// handle first endpoint
xend := round(x1)
yend := y1 + gradient*(xend-x1)
xgap := rfpart(x1 + .5)
xpxl1 := int(xend) // this will be used in the main loop
ypxl1 := int(ipart(yend))
plot(xpxl1, ypxl1, rfpart(yend)*xgap)
plot(xpxl1, ypxl1+1, fpart(yend)*xgap)
intery := yend + gradient // first y-intersection for the main loop
// handle second endpoint
xend = round(x2)
yend = y2 + gradient*(xend-x2)
xgap = fpart(x2 + 0.5)
xpxl2 := int(xend) // this will be used in the main loop
ypxl2 := int(ipart(yend))
plot(xpxl2, ypxl2, rfpart(yend)*xgap)
plot(xpxl2, ypxl2+1, fpart(yend)*xgap)
// main loop
for x := xpxl1 + 1; x <= xpxl2-1; x++ {
plot(x, int(ipart(intery)), rfpart(intery))
plot(x, int(ipart(intery))+1, fpart(intery))
intery = intery + gradient
}
}

View file

@ -0,0 +1,16 @@
package main
// Files required to build supporting package raster are found in:
// * This task (immediately above)
// * Bitmap
// * Grayscale image
// * Write a PPM file
import "raster"
func main() {
g := raster.NewGrmap(400, 300)
g.AaLine(7.4, 12.3, 307, 122.5)
g.AaLine(177.4, 12.3, 127, 222.5)
g.Bitmap().WritePpmFile("wu.ppm")
}

View file

@ -0,0 +1,25 @@
load'gl2'
coinsert'jgl2'
drawpt=:4 :0"0 1
glrgb <.(-.x)*255 255 255
glpixel y
)
drawLine=:3 :0 NB. drawline x1,y1,x2,y2
pts=. 2 2$y
isreversed=. </ |d=. -~/pts
r=. |.^:isreversed"1
pts=. /:~ pts \:"1 |d
gradient=. %~/ (\:|)d
'x y'=. |:pts
xend=. <.0.5+ x
yend=. y + gradient* xend-x
xgap=. -.1|x+0.5
n=. i. >: -~/ xend
'xlist ylist'=. (n*/~1,gradient) + ({.xend),({.yend)
weights=. ((2&}.,~ xgap*2&{.)&.(_1&|.) (,.~-.) 1|ylist)
weights (drawpt r)"1 2 (,:+&0 1)"1 xlist,.<.ylist
)

View file

@ -0,0 +1,2 @@
wd'pc win closeok; xywh 0 0 300 200;cc g isigraph; pas 0 0; pshow;'
glpaint drawLine 10 10 590 390

View file

@ -0,0 +1,155 @@
NoMainWin
WindowWidth = 270
WindowHeight = 290
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
Global variablesInitialized : variablesInitialized = 0
Global BackColor$ : BackColor$ = "0 0 0"
' BackColor$ = "255 255 255"
'now, right click randomizes BG
Global size : size = 1'4
global mousepoints.mouseX0, mousepoints.mouseY0, mousepoints.mouseX1, mousepoints.mouseY1
'StyleBits #main.gbox, 0, _WS_BORDER, 0, 0
GraphicBox #main.gbox, 0, 0, 253, 252
Open "Click Twice to Form Line" For Window As #main
Print #main, "TrapClose quit"
Print #main.gbox, "Down; Color Black"
Print #main.gbox, "Down; fill ";BackColor$
Print #main.gbox, "When leftButtonUp gBoxClick"
Print #main.gbox, "When rightButtonUp RandomBG"
Print #main.gbox, "Size "; size
result = drawAntiAliasedLine(126.5, 0, 126.5, 252, "255 0 0")
result = drawAntiAliasedLine(0, 126, 253, 126, "255 0 0")
result = drawAntiAliasedLine(0, 0, 253, 252, "255 0 0")
result = drawAntiAliasedLine(253, 0, 0, 252, "255 0 0")
Wait
Sub quit handle$
Close #main
End
End Sub
sub RandomBG handle$, MouseX, MouseY
BackColor$ = int(rnd(1)*256);" ";int(rnd(1)*256);" ";int(rnd(1)*256)
Print #main.gbox, "CLS; fill ";BackColor$
variablesInitialized = 0
end sub
Sub gBoxClick handle$, MouseX, MouseY
'We will use the mousepoints "struct" to hold the values
'that way they are retained between subroutine calls
If variablesInitialized = 0 Then
Print #main.gbox, "CLS; fill ";BackColor$
mousepoints.mouseX0 = MouseX
mousepoints.mouseY0 = MouseY
variablesInitialized = 1
Else
If variablesInitialized = 1 Then
mousepoints.mouseX1 = MouseX
mousepoints.mouseY1 = MouseY
variablesInitialized = 0
result = drawAntiAliasedLine(mousepoints.mouseX0, mousepoints.mouseY0, mousepoints.mouseX1, mousepoints.mouseY1, "255 0 0")
End If
End If
End Sub
Function Swap(Byref a,Byref b)
aTemp = b
b = a
a = aTemp
End Function
Function RoundtoInt(val)
RoundtoInt = Int(val + 0.5)
End Function
Function PlotAntiAliased(x, y, RGB$, b, steep)
RGB$ = Int(Val(Word$(BackColor$, 1))*(1-b) + Val(Word$(RGB$, 1)) * b) ; " " ; _
Int(Val(Word$(BackColor$, 2))*(1-b) + Val(Word$(RGB$, 3)) * b) ; " " ; _
Int(Val(Word$(BackColor$, 3))*(1-b) + Val(Word$(RGB$, 2)) * b)
if steep then 'x and y reversed
Print #main.gbox, "Down; Color " + RGB$ + "; Set " + str$(y) + " " + str$(x)
else
Print #main.gbox, "Down; Color " + RGB$ + "; Set " + str$(x) + " " + str$(y)
end if
End Function
Function fracPart(x)
fracPart = (x Mod 1)
End function
Function invFracPart(x)
invFracPart = (1 - fracPart(x))
End Function
Function drawAntiAliasedLine(x1, y1, x2, y2, RGB$)
If (x2 - x1)=0 Or (y2 - y1)=0 Then
Print #main.gbox, "Down; Color " + RGB$
result = BresenhamLine(x1, y1, x2, y2)
Exit Function
End If
steep = abs(x2 - x1) < abs(y2 - y1)
if steep then 'x and y should be reversed
result = Swap(x1, y1)
result = Swap(x2, y2)
end if
If (x2 < x1) Then
result = Swap(x1, x2)
result = Swap(y1, y2)
End If
dx = (x2 - x1)
dy = (y2 - y1)
grad = (dy/ dx)
'Handle the First EndPoint
xend = RoundtoInt(x1)
yend = y1 + grad * (xend - x1)
xgap = invFracPart(x1 + 0.5)
ix1 = xend
iy1 = Int(yend)
result = PlotAntiAliased(ix1, iy1, RGB$, invFracPart(yend) * xgap, steep )
result = PlotAntiAliased(ix1, (iy1 + size), RGB$, fracPart(yend) * xgap, steep )
yf = (yend + grad)
'Handle the Second EndPoint
xend = RoundtoInt(x2)
yend = y2 + grad * (xend - x2)
xgap = fracPart(x2 + 0.5)
ix2 = xend
iy2 = Int(yend)
result = PlotAntiAliased(ix2, iy2, RGB$, invFracPart(yend) * xgap, steep )
result = PlotAntiAliased(ix2, (iy2 + size), RGB$, fracPart(yend) * xgap, steep )
For x = ix1 + 1 To ix2 - 1
result = PlotAntiAliased(x, Int(yf), RGB$, invFracPart(yf), steep )
result = PlotAntiAliased(x, (Int(yf) + size), RGB$, fracPart(yf), steep )
yf = (yf + grad)
Next x
End Function
Function BresenhamLine(x0, y0, x1, y1)
dx = Abs(x1 - x0)
dy = Abs(y1 - y0)
sx = ((x1 > x0) + Not(x0 < x1))
sy = ((y1 > y0) + Not(y0 < y1))
errornum = (dx - dy)
Do While 1
Print #main.gbox, "Set " + str$(x0) + " " + str$(y0)
If (x0 = x1) And (y0 = y1) Then Exit Do
errornum2 = (2 * errornum)
If errornum2 > (-1 * dy) Then
errornum = (errornum - dy)
x0 = (x0 + sx)
End If
If errornum2 < dx Then
errornum = (errornum + dx)
y0 = (y0 + sy)
End If
Loop
End Function

View file

@ -0,0 +1,60 @@
sub plot(\x, \y, \c) { say "plot {x} {y} {c}" }
sub fpart(\x) { x - floor(x) }
sub draw-line(@a is copy, @b is copy) {
my Bool \steep = abs(@b[1] - @a[1]) > abs(@b[0] - @a[0]);
my $plot = &OUTER::plot;
if steep {
$plot = -> $y, $x, $c { plot($x, $y, $c) }
@a.=reverse;
@b.=reverse;
}
if @a[0] > @b[0] { my @t = @a; @a = @b; @b = @t }
my (\x0,\y0) = @a;
my (\x1,\y1) = @b;
my \dx = x1 - x0;
my \dy = y1 - y0;
my \gradient = dy / dx;
# handle first endpoint
my \x-end1 = round(x0);
my \y-end1 = y0 + gradient * (x-end1 - x0);
my \x-gap1 = 1 - round(x0 + 0.5);
my \x-pxl1 = x-end1; # this will be used in the main loop
my \y-pxl1 = floor(y-end1);
my \c1 = fpart(y-end1) * x-gap1;
$plot(x-pxl1, y-pxl1 , 1 - c1) unless c1 == 1;
$plot(x-pxl1, y-pxl1 + 1, c1 ) unless c1 == 0;
# handle second endpoint
my \x-end2 = round(x1);
my \y-end2 = y1 + gradient * (x-end2 - x1);
my \x-gap2 = fpart(x1 + 0.5);
my \x-pxl2 = x-end2; # this will be used in the main loop
my \y-pxl2 = floor(y-end2);
my \c2 = fpart(y-end2) * x-gap2;
my \intery = y-end1 + gradient;
# main loop
for (x-pxl1 + 1 .. x-pxl2 - 1)
Z
(intery, intery + gradient ... *)
-> \x,\y {
my \c = fpart(y);
$plot(x, floor(y) , 1 - c) unless c == 1;
$plot(x, floor(y) + 1, c ) unless c == 0;
}
$plot(x-pxl2, y-pxl2 , 1 - c2) unless c2 == 1;
$plot(x-pxl2, y-pxl2 + 1, c2 ) unless c2 == 0;
}
draw-line [0,1], [10,2];

View file

@ -0,0 +1,57 @@
(scl 2)
(de plot (Img X Y C)
(set (nth Img (*/ Y 1.0) (*/ X 1.0)) (- 100 C)) )
(de ipart (X)
(* 1.0 (/ X 1.0)) )
(de iround (X)
(ipart (+ X 0.5)) )
(de fpart (X)
(% X 1.0) )
(de rfpart (X)
(- 1.0 (fpart X)) )
(de xiaolin (Img X1 Y1 X2 Y2)
(let (DX (- X2 X1) DY (- Y2 Y1))
(use (Grad Xend Yend Xgap Xpxl1 Ypxl1 Xpxl2 Ypxl2 Intery)
(when (> (abs DY) (abs DX))
(xchg 'X1 'Y1 'X2 'Y2) )
(when (> X1 X2)
(xchg 'X1 'X2 'Y1 'Y2) )
(setq
Grad (*/ DY 1.0 DX)
Xend (iround X1)
Yend (+ Y1 (*/ Grad (- Xend X1) 1.0))
Xgap (rfpart (+ X1 0.5))
Xpxl1 Xend
Ypxl1 (ipart Yend) )
(plot Img Xpxl1 Ypxl1 (*/ (rfpart Yend) Xgap 1.0))
(plot Img Xpxl1 (+ 1.0 Ypxl1) (*/ (fpart Yend) Xgap 1.0))
(setq
Intery (+ Yend Grad)
Xend (iround X2)
Yend (+ Y2 (*/ Grad (- Xend X2) 1.0))
Xgap (fpart (+ X2 0.5))
Xpxl2 Xend
Ypxl2 (ipart Yend) )
(plot Img Xpxl2 Ypxl2 (*/ (rfpart Yend) Xgap 1.0))
(plot Img Xpxl2 (+ 1.0 Ypxl2) (*/ (fpart Yend) Xgap 1.0))
(for (X (+ Xpxl1 1.0) (>= (- Xpxl2 1.0) X) (+ X 1.0))
(plot Img X (ipart Intery) (rfpart Intery))
(plot Img X (+ 1.0 (ipart Intery)) (fpart Intery))
(inc 'Intery Grad) ) ) ) )
(let Img (make (do 90 (link (need 120 99)))) # Create image 120 x 90
(xiaolin Img 10.0 10.0 110.0 80.0) # Draw lines
(xiaolin Img 10.0 10.0 110.0 45.0)
(xiaolin Img 10.0 80.0 110.0 45.0)
(xiaolin Img 10.0 80.0 110.0 10.0)
(out "img.pgm" # Write to bitmap file
(prinl "P2")
(prinl 120 " " 90)
(prinl 100)
(for Y Img (apply printsp Y)) ) )

View file

@ -0,0 +1,72 @@
Macro PlotB(x, y, Color, b)
Plot(x, y, RGB(Red(Color) * (b), Green(Color) * (b), Blue(Color) * (b)))
EndMacro
Procedure.f fracPart(x.f)
ProcedureReturn x - Int(x)
EndProcedure
Procedure.f invFracPart(x.f)
ProcedureReturn 1.0 - fracPart(x)
EndProcedure
Procedure drawAntiAliasedLine(x1.f, y1.f, x2.f, y2.f, color)
Protected.f dx, dy, xend, yend, grad, yf, xgap, ix1, iy1, ix2, iy2
Protected x
dx = x2 - x1
dy = y2 - y1
If Abs(dx) < Abs(dy)
Swap x1, y1
Swap x2, y2
Swap dx, dy
EndIf
If x2 < x1
Swap x1, x2
Swap y1, y2
EndIf
grad = dy / dx
;handle first endpoint
xend = Round(x1, #pb_round_nearest)
yend = y1 + grad * (xend - x1)
xgap = invFracPart(x1 + 0.5)
ix1 = xend ;this will be used in the MAIN loop
iy1 = Int(yend)
PlotB(ix1, iy1, color, invFracPart(yend) * xgap)
PlotB(ix1, iy1 + 1, color, fracPart(yend) * xgap)
yf = yend + grad ;first y-intersection for the MAIN loop
;handle second endpoint
xend = Round(x2, #pb_round_nearest)
yend = y2 + grad * (xend - x2)
xgap = fracPart(x2 + 0.5)
ix2 = xend ;this will be used in the MAIN loop
iy2 = Int(yend)
PlotB(ix2, iy2, color, invFracPart(yend) * xgap)
PlotB(ix2, iy2 + 1, color, fracPart(yend) * xgap)
;MAIN loop
For x = ix1 + 1 To ix2 - 1
PlotB(x, Int(yf), color, invFracPart(yf))
PlotB(x, Int(yf) + 1, color, fracPart(yf))
yf + grad
Next
EndProcedure
Define w = 200, h = 200, img = 1
CreateImage(img, w, h) ;img is internal id of the image
OpenWindow(0, 0, 0, w, h,"Xiaolin Wu's line algorithm", #PB_Window_SystemMenu)
StartDrawing(ImageOutput(img))
drawAntiAliasedLine(80,20, 130,80, RGB(255, 0, 0))
StopDrawing()
ImageGadget(0, 0, 0, w, h, ImageID(img))
Define event
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow

View file

@ -0,0 +1,77 @@
"""Script demonstrating drawing of anti-aliased lines using Xiaolin Wu's line
algorithm
usage: python xiaolinwu.py [output-file]
"""
from __future__ import division
import sys
from PIL import Image
def _fpart(x):
return x - int(x)
def _rfpart(x):
return 1 - _fpart(x)
def putpixel(img, xy, color, alpha=1):
"""Paints color over the background at the point xy in img.
Use alpha for blending. alpha=1 means a completely opaque foreground.
"""
c = tuple(map(lambda bg, fg: int(round(alpha * fg + (1-alpha) * bg)),
img.getpixel(xy), color))
img.putpixel(xy, c)
def draw_line(img, p1, p2, color):
"""Draws an anti-aliased line in img from p1 to p2 with the given color."""
x1, y1, x2, y2 = p1 + p2
dx, dy = x2-x1, y2-y1
steep = abs(dx) < abs(dy)
p = lambda px, py: ((px,py), (py,px))[steep]
if steep:
x1, y1, x2, y2, dx, dy = y1, x1, y2, x2, dy, dx
if x2 < x1:
x1, x2, y1, y2 = x2, x1, y2, y1
grad = dy/dx
intery = y1 + _rfpart(x1) * grad
def draw_endpoint(pt):
x, y = pt
xend = round(x)
yend = y + grad * (xend - x)
xgap = _rfpart(x + 0.5)
px, py = int(xend), int(yend)
putpixel(img, (px, py), color, _rfpart(yend) * xgap)
putpixel(img, (px, py+1), color, _fpart(yend) * xgap)
return px
xstart = draw_endpoint(p(*p1)) + 1
xend = draw_endpoint(p(*p2))
for x in range(xstart, xend):
y = int(intery)
putpixel(img, p(x, y), color, _rfpart(intery))
putpixel(img, p(x, y+1), color, _fpart(intery))
intery += grad
if __name__ == '__main__':
if len(sys.argv) != 2:
print 'usage: python xiaolinwu.py [output-file]'
sys.exit(-1)
blue = (0, 0, 255)
yellow = (255, 255, 0)
img = Image.new("RGB", (500,500), blue)
for a in range(10, 431, 60):
draw_line(img, (10, 10), (490, a), yellow)
draw_line(img, (10, 10), (a, 490), yellow)
draw_line(img, (10, 10), (490, 490), yellow)
filename = sys.argv[1]
img.save(filename)
print 'image saved to', filename

View file

@ -0,0 +1,82 @@
/*REXX program plots/draws a line using the Xiaolin Wu line algorithm.*/
background = 'fa'x /*background char: middle-dot. */
image. = background /*fill the array with middle-dots*/
plotC = '' /*chars used for plotting points.*/
EoE = 1000 /*EOE = End Of Earth, er... plot.*/
do j=-EoE to +EoE /*draw grid from lowest──►highest*/
image.j.0 = '' /*draw the horizontal axis. */
image.0.j = '' /* " " verical " */
end /*j*/
image.0.0 = '' /*"draw" the axis origin (char). */
parse arg xi yi xf yf . /*allow specifying line-end pts. */
if xi=='' | xi==',' then xi = 1 /*if not specified, use default. */
if yi=='' | yi==',' then yi = 2 /* " " " " " */
if xf=='' | xf==',' then xf = 11 /* " " " " " */
if yf=='' | yf==',' then yf = 12 /* " " " " " */
minX=0; minY=0 /*used as limits for plotting. */
maxX=0; maxY=0 /* " " " " " */
call line_draw xi, yi, xf, yf /*call subroutine and draw line. */
border = 2 /*allow additional space for plot*/
minX=minX-border*2; maxX=maxX+border*2
minY=minY-border ; maxY=maxY+border
do y=maxY by -1 to minY; _= /*build a row*/
do x=minX to maxX
_=_ || image.x.y
end /*x*/
say _ /*display row*/
end /*y*/
exit /*stick a fork in it, we're done.*/
/*────────────────────────────────DRAW_LINE subroutine──────────────────*/
line_draw: procedure expose background image. minX maxX minY maxY plotC
parse arg x1, y1, x2, y2; switchXY=0; dx=x2-x1
dy=y2-y1
if abs(dx)<abs(dy) then do
parse value x1 y1 with y1 x1 /*swap x1 & y1*/
parse value x2 y2 with y2 x2 /*swap x2 & y2*/
parse value dx dy with dy dx /*swap dx & dy*/
end
if x2<x1 then do
parse value x1 x2 with x2 x1 /*swap x1 & x2*/
parse value y1 y2 with y2 y1 /*swap y1 & y2*/
switchXY=1
end
gradient = dy/dx
xend = round(x1) /*────1st endpoint────────────────────*/
yend = y1 + gradient * (xend-x1)
intery = yend + gradient
xgap = 1 - fpart(x1+.5)
xpx11 = xend; ypx11 = floor(yend); ypx11_=ypx11+1
call plotXY xpx11, ypx11, brite(1-fpart(yend*xgap)),switchXY
call plotXY xpx11, ypx11_, brite( fpart(yend*xgap)),switchXY
xend = round(x2) /*────2nd endpoint────────────────────*/
yend = y2 + gradient * (xend-x2)
xgap = fpart(x2+.5)
xpx12 = xend; ypx12 = floor(yend); ypx12_=ypx12+1
call plotXY xpx12, ypx12, brite(1-fpart(yend*xgap)), switchXY
call plotXY xpx12, ypx12_, brite( fpart(yend*xgap)), switchXY
do x=xpx11+1 to xpx12-1 /*────draw the line───────────────────*/
!intery = floor(intery)
!intery_ = !intery+1
call plotXY x, !intery, brite(1-fpart(intery)), switchXY
call plotXY x, !intery_, brite( fpart(intery)), switchXY
intery = intery + gradient
end /*x*/
return
/*────────────────────────────────BRITE subroutine──────────────────────*/
brite: procedure expose background plotC; parse arg p
return substr(background || plotC, 1+round(abs(p)*length(plotC)), 1)
/*────────────────────────────────PLOTXY subroutine─────────────────────*/
plotXY: procedure expose image. minX maxX minY maxY
parse arg xx, yy, bc, switchYX; if switchYX then parse arg yy, xx
image.xx.yy=bc; minX=min(minX,xx); maxX=max(maxX,xx)
minY=min(minY,yy); maxY=max(maxY,yy)
return
/*────────────────────────────────FLOOR subroutine──────────────────────*/
floor: procedure; parse arg ?; _=trunc(?); return _-(?<0)*(?\=_)
/*────────────────────────────────FPART subroutine──────────────────────*/
fpart: procedure; parse arg ?; return abs(?-trunc(?))
/*────────────────────────────────ROUND subroutine─────────arg2 is place*/
round: return format(arg(1), , word(arg(2) 0, 1))

View file

@ -0,0 +1,67 @@
def ipart(n); n.truncate; end
def fpart(n); n - ipart(n); end
def rfpart(n); 1.0 - fpart(n); end
class Pixmap
def draw_line_antialised(p1, p2, colour)
x1, y1 = p1.x, p1.y
x2, y2 = p2.x, p2.y
steep = (y2 - y1).abs > (x2 - x1).abs
if steep
x1, y1 = y1, x1
x2, y2 = y2, x2
end
if x1 > x2
x1, x2 = x2, x1
y1, y2 = y2, y1
end
deltax = x2 - x1
deltay = (y2 - y1).abs
gradient = 1.0 * deltay / deltax
# handle the first endpoint
xend = x1.round
yend = y1 + gradient * (xend - x1)
xgap = rfpart(x1 + 0.5)
xpxl1 = xend
ypxl1 = ipart(yend)
put_colour(xpxl1, ypxl1, colour, steep, rfpart(yend)*xgap)
put_colour(xpxl1, ypxl1 + 1, colour, steep, fpart(yend)*xgap)
itery = yend + gradient
# handle the second endpoint
xend = x2.round
yend = y2 + gradient * (xend - x2)
xgap = rfpart(x2 + 0.5)
xpxl2 = xend
ypxl2 = ipart(yend)
put_colour(xpxl2, ypxl2, colour, steep, rfpart(yend)*xgap)
put_colour(xpxl2, ypxl2 + 1, colour, steep, fpart(yend)*xgap)
# in between
(xpxl1 + 1).upto(xpxl2 - 1).each do |x|
put_colour(x, ipart(itery), colour, steep, rfpart(itery))
put_colour(x, ipart(itery) + 1, colour, steep, fpart(itery))
itery = itery + gradient
end
end
def put_colour(x, y, colour, steep, c)
x, y = y, x if steep
self[x, y] = anti_alias(colour, self[x, y], c)
end
def anti_alias(new, old, ratio)
blended = new.values.zip(old.values).map {|n, o| (n*ratio + o*(1.0 - ratio)).round}
RGBColour.new(*blended)
end
end
bitmap = Pixmap.new(500, 500)
bitmap.fill(RGBColour::BLUE)
10.step(430, 60) do |a|
bitmap.draw_line_antialised(Pixel[10, 10], Pixel[490,a], RGBColour::YELLOW)
bitmap.draw_line_antialised(Pixel[10, 10], Pixel[a,490], RGBColour::YELLOW)
end
bitmap.draw_line_antialised(Pixel[10, 10], Pixel[490,490], RGBColour::YELLOW)

View file

@ -0,0 +1,88 @@
package require Tcl 8.5
package require Tk
proc ::tcl::mathfunc::ipart x {expr {int($x)}}
proc ::tcl::mathfunc::fpart x {expr {$x - int($x)}}
proc ::tcl::mathfunc::rfpart x {expr {1.0 - fpart($x)}}
proc drawAntialiasedLine {image colour p1 p2} {
lassign $p1 x1 y1
lassign $p2 x2 y2
set steep [expr {abs($y2 - $y1) > abs($x2 - $x1)}]
if {$steep} {
lassign [list $x1 $y1] y1 x1
lassign [list $x2 $y2] y2 x2
}
if {$x1 > $x2} {
lassign [list $x1 $x2] x2 x1
lassign [list $y1 $y2] y2 y1
}
set deltax [expr {$x2 - $x1}]
set deltay [expr {abs($y2 - $y1)}]
set gradient [expr {1.0 * $deltay / $deltax}]
# handle the first endpoint
set xend [expr {round($x1)}]
set yend [expr {$y1 + $gradient * ($xend - $x1)}]
set xgap [expr {rfpart($x1 + 0.5)}]
set xpxl1 $xend
set ypxl1 [expr {ipart($yend)}]
plot $image $colour $steep $xpxl1 $ypxl1 [expr {rfpart($yend)*$xgap}]
plot $image $colour $steep $xpxl1 [expr {$ypxl1+1}] [expr {fpart($yend)*$xgap}]
set itery [expr {$yend + $gradient}]
# handle the second endpoint
set xend [expr {round($x2)}]
set yend [expr {$y2 + $gradient * ($xend - $x2)}]
set xgap [expr {rfpart($x2 + 0.5)}]
set xpxl2 $xend
set ypxl2 [expr {ipart($yend)}]
plot $image $colour $steep $xpxl2 $ypxl2 [expr {rfpart($yend)*$xgap}]
plot $image $colour $steep $xpxl2 [expr {$ypxl2+1}] [expr {fpart($yend)*$xgap}]
for {set x [expr {$xpxl1 + 1}]} {$x < $xpxl2} {incr x} {
plot $image $colour $steep $x [expr {ipart($itery)}] [expr {rfpart($itery)}]
plot $image $colour $steep $x [expr {ipart($itery) + 1}] [expr {fpart($itery)}]
set itery [expr {$itery + $gradient}]
}
}
proc plot {image colour steep x y c} {
set point [expr {$steep ? [list $y $x] : [list $x $y]}]
set newColour [antialias $colour [getPixel $image $point] $c]
setPixel $image $newColour $point
}
proc antialias {newColour oldColour c} {
# get the new colour r,g,b
if {[scan $newColour "#%2x%2x%2x%c" nr ng gb -] != 3} {
scan [colour2rgb $newColour] "#%2x%2x%2x" nr ng nb
}
# get the current colour r,g,b
scan $oldColour "#%2x%2x%2x" cr cg cb
# blend the colours in the ratio defined by "c"
foreach new [list $nr $ng $nb] curr [list $cr $cg $cb] {
append blend [format {%02x} [expr {round($new*$c + $curr*(1.0-$c))}]]
}
return #$blend
}
proc colour2rgb {color_name} {
foreach part [winfo rgb . $color_name] {
append colour [format %02x [expr {$part >> 8}]]
}
return #$colour
}
set img [newImage 500 500]
fill $img blue
for {set a 10} {$a < 500} {incr a 60} {
drawAntialiasedLine $img yellow {10 10} [list 490 $a]
drawAntialiasedLine $img yellow {10 10} [list $a 490]
}
toplevel .wu
label .wu.l -image $img
pack .wu.l