Bitmap/Bresenham's line algorithm

You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Using the data storage type defined on the Bitmap page for raster graphics images,
draw a line given two points with Bresenham's line algorithm.
11l
T Colour = BVec3 V black = Colour(0, 0, 0) V white = Colour(255, 255, 255) T Bitmap Int width, height Colour background [[Colour]] map F (width = 40, height = 40, background = white) assert(width > 0 & height > 0) .width = width .height = height .background = background .map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background)) F fillrect(x, y, width, height, colour = black) assert(x >= 0 & y >= 0 & width > 0 & height > 0) L(h) 0 .< height L(w) 0 .< width .map[y + h][x + w] = colour F chardisplay() V txt = .map.map(row -> row.map(bit -> (I bit == @@.background {‘ ’} E ‘@’)).join(‘’)) txt = txt.map(row -> ‘|’row‘|’) txt.insert(0, ‘+’(‘-’ * .width)‘+’) txt.append(‘+’(‘-’ * .width)‘+’) print(reversed(txt).join("\n")) F set(x, y, colour = black) .map[y][x] = colour F get(x, y) R .map[y][x] F line(x0, y0, x1, y1) ‘Bresenham's line algorithm’ V dx = abs(x1 - x0) V dy = abs(y1 - y0) V (x, y) = (x0, y0) V sx = I x0 > x1 {-1} E 1 V sy = I y0 > y1 {-1} E 1 I dx > dy V err = dx / 2.0 L x != x1 .set(x, y) err -= dy I err < 0 y += sy err += dx x += sx E V err = dy / 2.0 L y != y1 .set(x, y) err -= dx I err < 0 x += sx err += dy y += sy .set(x, y) V bitmap = Bitmap(17, 17) L(x0, y0, x1, y1) ((1, 8, 8, 16), (8, 16, 16, 8), (16, 8, 8, 1), (8, 1, 1, 8)) bitmap.line(x0, y0, x1, y1) bitmap.chardisplay()
- Output:
+-----------------+ | @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @| | @ @ | | @ @ | | @ @@ | | @ @ | | @ @ | | @ @ | | @ | | | +-----------------+
360 Assembly
* Bitmap/Bresenham's line algorithm - 13/05/2019 BRESENH CSECT USING BRESENH,R13 base register B 72(R15) skip savearea DC 17F'0' savearea SAVE (14,12) save previous context ST R13,4(R15) link backward ST R15,8(R13) link forward LR R13,R15 set addressability LA R10,DATAXY @dataxy LA R8,1 p=1 DO WHILE=(C,R8,LE,=A(POINTS)) do p=1 to points L R6,0(R10) x=dataxy((p-1)*2+1) L R7,4(R10) y=dataxy((p-1)*2+2) IF C,R8,EQ,=F'1' THEN if p=1 then ST R6,MINX minx=x ST R6,MAXX maxx=x ST R7,MINY miny=y ST R7,MAXY maxy=y ENDIF , endif IF C,R6,LT,MINX THEN if x<minx then ST R6,MINX minx=x ENDIF , endif IF C,R6,GT,MAXX THEN if x>maxx then ST R6,MAXX maxx=x ENDIF , endif IF C,R7,LT,MINY THEN if y<miny then ST R7,MINY miny=y ENDIF , endif IF C,R7,GT,MAXY THEN if y>maxy then ST R7,MAXY maxy=y ENDIF , endif LA R10,8(R10) @dataxy+=8 LA R8,1(R8) p++ ENDDO , enddo p L R1,MINX minx S R1,=A(BORDER*2) -border*2 ST R1,MINX minx=minx-border*2 L R1,MAXX maxx A R1,=A(BORDER*2) +border*2 ST R1,MAXX maxx=maxx+border*2 L R1,MINY miny S R1,=A(BORDER) -border ST R1,MINY miny=miny-border L R1,MAXY maxy A R1,=A(BORDER) +border ST R1,MAXY maxy=maxy+border L R1,MINX minx LCR R1,R1 - A R1,=F'1' +1 ST R1,OX ox=-minx+1 L R1,MINY miny LCR R1,R1 - A R1,=F'1' +1 ST R1,OY oy=-miny+1 LA R1,HMAPX hbound(map,1) S R1,OX wx=hbound(map,1)-ox IF C,R1,LT,MAXX THEN if maxx>wx then ST R1,MAXX maxx=wx ENDIF , endif LA R1,HMAPY hbound(map,2) S R1,OY wy=hbound(map,2)-oy IF C,R1,LT,MAXY THEN if maxy>wy then ST R1,MAXY maxy=wy ENDIF , endif L R6,MINX x=minx DO WHILE=(C,R6,LE,MAXX) do x=minx to maxx L R1,OY oy BCTR R1,0 1 MH R1,=AL2(HMAPX) dim(x) AR R1,R6 x A R1,OX ox LA R1,MAP-1(R1) map(0+oy,x+ox) MVC 0(1,R1),=C'-' map(0+oy,x+ox)='-' A R6,=F'1' x++ ENDDO , enddo x L R7,MINY y=miny DO WHILE=(C,R7,LE,MAXY) do y=miny to maxy LR R1,R7 y A R1,OY +oy BCTR R1,0 -1 MH R1,=AL2(HMAPX) *dim(x) A R1,OX +ox LA R1,MAP-1(R1) @map(y+oy,0+ox) MVC 0(1,R1),=C'|' map(y+oy,0+ox)='|' A R7,=F'1' y++ ENDDO , enddo y L R1,OY +oy BCTR R1,0 -1 MH R1,=AL2(HMAPX) *dim(x) A R1,OX +ox LA R1,MAP-1(R1) @map(0+oy,0+ox) MVC 0(1,R1),=C'+' map(0+oy,0+ox)='+' LA R10,POINTS points BCTR R10,0 pn=points-1 LA R9,DATAXY @dataxy LA R8,1 p=1 DO WHILE=(CR,R8,LE,R10) do p=1 to points-1 L R6,0(R9) x=dataxy((p-1)*2+1) L R7,4(R9) y=dataxy((p-1)*2+2) L R4,8(R9) xf=dataxy(p*2+1) L R5,12(R9) yf=dataxy(p*2+2) LR R2,R4 xf SR R2,R6 -x LPR R2,R2 abs() ST R2,DX dx=abs(xf-x) LR R2,R5 xf SR R2,R7 -y LPR R2,R2 abs() ST R2,DY dy=abs(yf-y) IF CR,R6,LT,R4 THEN if x<xf then MVC SX,=F'1' sx=+1 ELSE , else MVC SX,=F'-1' sx=-1 ENDIF , endif IF CR,R7,LT,R5 THEN if y<yf then MVC SY,=F'1' sy=+1 ELSE , else MVC SY,=F'-1' sy=-1 ENDIF , endif L R2,DX dx S R2,DY -dy ST R2,ERR err=dx-dy LOOP EQU * loop forever LR R1,R7 y A R1,OY +oy BCTR R1,0 -1 MH R1,=AL2(HMAPX) *dim(x) AR R1,R6 +x A R1,OX +ox LA R1,MAP-1(R1) @map(y+oy,x+ox) MVC 0(1,R1),=C'X' map(y+oy,x+ox)='X' CR R6,R4 if x=xf BNE STAYDO ~ CR R7,R5 if y=yf BE EXITLOOP if x=xf and y=yf then leave loop STAYDO L R0,ERR err A R0,ERR err+err ST R0,ERR2 err2=err+err L R0,DY dy LCR R0,R0 -dy IF C,R0,LT,ERR2 THEN if err2>-dy then A R0,ERR -dy+err ST R0,ERR err=err-dy A R6,SX x=x+sx ENDIF , endif L R0,DX dx IF C,R0,GT,ERR2 THEN if err2<dx then L R0,ERR err A R0,DX +dx ST R0,ERR err=err+dx A R7,SY y=y+sy ENDIF , endif B LOOP endloop EXITLOOP LA R9,8(R9) @dataxy+=2 LA R8,1(R8) p++ ENDDO , enddo p LA R9,MAP+(HMAPX*HMAPY)-HMAPX @map L R7,MAXY y=maxy DO WHILE=(C,R7,GE,MINY) do y=maxy to miny by -1 MVC PG(HMAPX),0(R9) output map(x,*) XPRNT PG,L'PG print buffer S R9,=A(HMAPX) @pg S R7,=F'1' y-- ENDDO , enddo y L R13,4(0,R13) restore previous savearea pointer RETURN (14,12),RC=0 restore registers from calling sav BORDER EQU 2 border size POINTS EQU (MAP-DATAXY)/L'DATAXY/2 HMAPX EQU 24 dim(map,1) HMAPY EQU 20 dim(map,2) DATAXY DC F'1',F'8',F'8',F'16',F'16',F'8',F'8',F'1',F'1',F'8' MAP DC (HMAPX*HMAPY)CL1'.' map(hmapx,hmapy) OX DS F OY DS F MINX DS F MAXX DS F MINY DS F MAXY DS F DX DS F DY DS F SX DS F SY DS F ERR DS F ERR2 DS F PG DC CL80' ' buffer REGEQU END BRESENH
- Output:
...|.................... ...|.................... ...|.......X............ ...|......X.X........... ...|.....X...X.......... ...|....X.....X......... ...|...X.......X........ ...|...X........X....... ...|..X..........X...... ...|.X............X..... ...|X..............X.... ...|.X............X..... ...|..X..........X...... ...|...X.......XX....... ...|....X.....X......... ...|.....X...X.......... ...|......X.X........... ...|.......X............ ---+-------------------- ...|....................
Action!
Part of the task is available in RGBLINE.ACT.
INCLUDE "H6:RGBLINE.ACT" ;from task Bresenham's line algorithm RGB black,yellow,violet,blue PROC DrawImage(RgbImage POINTER img BYTE x,y) RGB POINTER ptr BYTE i,j ptr=img.data FOR j=0 TO img.h-1 DO FOR i=0 TO img.w-1 DO IF RgbEqual(ptr,yellow) THEN Color=1 ELSEIF RgbEqual(ptr,violet) THEN Color=2 ELSEIF RgbEqual(ptr,blue) THEN Color=3 ELSE Color=0 FI Plot(x+i,y+j) ptr==+RGBSIZE OD OD RETURN PROC Main() RgbImage img BYTE CH=$02FC,width=[81],height=[51],st=[5] BYTE ARRAY ptr(12393) BYTE c,i,n INT x,y,nx,ny RGB POINTER col Graphics(7+16) SetColor(0,13,12) ;yellow SetColor(1,4,8) ;violet SetColor(2,8,6) ;blue SetColor(4,0,0) ;black RgbBlack(black) RgbYellow(yellow) RgbViolet(violet) RgbBlue(blue) InitRgbImage(img,width,height,ptr) FillRgbImage(img,black) nx=width/st ny=height/st FOR n=0 TO 2*nx+2*ny-1 DO IF n MOD 3=0 THEN col=yellow ELSEIF n MOD 3=1 THEN col=violet ELSE col=blue FI IF n<nx THEN x=n*st y=0 ELSEIF n<nx+ny THEN x=width-1 y=(n-nx)*st ELSEIF n<2*nx+ny THEN x=width-1-(n-nx-ny)*st y=height-1 ELSE x=0 y=height-1-(n-2*nx-ny)*st FI RgbLine(img,width/2,height/2,x,y,col) OD DrawImage(img,(160-width)/2,(96-height)/2) DO UNTIL CH#$FF OD CH=$FF RETURN
- Output:
Screenshot from Atari 8-bit computer
Ada
procedureLine(Picture: inoutImage;Start,Stop: Point;Color: Pixel)isDX:constantFloat:=absFloat(Stop.X-Start.X);DY:constantFloat:=absFloat(Stop.Y-Start.Y);Err:Float;X:Positive:=Start.X;Y:Positive:=Start.Y;Step_X:Integer:=1;Step_Y:Integer:=1;beginifStart.X>Stop.XthenStep_X:=-1;endif;ifStart.Y>Stop.YthenStep_Y:=-1;endif;ifDX>DYthenErr:=DX/2.0;whileX/=Stop.XloopPicture(X,Y):=Color;Err:=Err-DY;ifErr<0.0thenY:=Y+Step_Y;Err:=Err+DX;endif;X:=X+Step_X;endloop;elseErr:=DY/2.0;whileY/=Stop.YloopPicture(X,Y):=Color;Err:=Err-DX;ifErr<0.0thenX:=X+Step_X;Err:=Err+DY;endif;Y:=Y+Step_Y;endloop;endif;Picture(X,Y):=Color;-- Ensure dots to be drawnendLine;
The test program's
X:Image(1..16,1..16);beginFill(X,White);Line(X,(1,8),(8,16),Black);Line(X,(8,16),(16,8),Black);Line(X,(16,8),(8,1),Black);Line(X,(8,1),(1,8),Black);Print(X);
sample output
H H H H H H HH H H H H H H H H H H H H H H H H H H H H H H H
ALGOL 68
File: prelude/Bitmap.a68 is on Rosetta Code at ALGOL 68/prelude#prelude/Bitmap.a68
File: prelude/Bitmap/Bresenhams_line_algorithm.a68 is on Rosetta Code at ALGOL 68/prelude#prelude/Bitmap/Bresenhams_line_algorithm.a68
File: test/Bitmap/Bresenhams_line_algorithm.a68
#!/usr/bin/a68g --script # # -*- coding: utf-8 -*- # PR READ "prelude/Bitmap.a68" PR; PR READ "prelude/Bitmap/Bresenhams_line_algorithm.a68" PR; ### The test program: ### ( REF IMAGE x = INIT LOC[1:16, 1:16]PIXEL; (fill OF class image)(x, white OF class image); (line OF class image)(x, ( 1, 8), ( 8,16), black OF class image); (line OF class image)(x, ( 8,16), (16, 8), black OF class image); (line OF class image)(x, (16, 8), ( 8, 1), black OF class image); (line OF class image)(x, ( 8, 1), ( 1, 8), black OF class image); (print OF class image)(x) )
- Output:
ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffff000000ffffff000000ffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffff000000ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff000000000000ffffffffffffffffffffffff ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffff ffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffff 000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000 ffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffff ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffff ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffff000000ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffff000000ffffff000000ffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff
Applesoft BASIC
10HGR:FULLSCREEN=PEEK(49234)20HCOLOR=330FORN=3TO279STEP440X1=276:Y1=189:X2=N:Y2=1:GOSUB100"PLOT LINE"50NEXTN60FORN=3TO191STEP370X1=276:Y1=190:X2=2:Y2=N:GOSUB100"PLOT LINE"80NEXTN90END100DX=ABS(X2-X1)110SX=SGN(X2-X1)120DY=-ABS(Y2-Y1)130SY=SGN(Y2-Y1)140ERR=DX+DY150FORWHILE=0TO1STEP0160HPLOTX1,Y1170IFX1=X2ANDY1=Y2THENRETURN180E2=2*ERR190IFE2>=DYANDX1=X2THENRETURN200IFE2>=DYTHENERR=ERR+DY:X1=X1+SX210IFE2<=DXANDY1=Y2THENRETURN220IFE2<=DXTHENERR=ERR+DX:Y1=Y1+SY230NEXTWHILE
Arturo
; Bitmap object definitiondefine:bitmap[init:method[width:integerheight:integer][\width:width\height:height\grid:array.of:@[widthheight]false]setOn:method[x:integery:integer][\grid\[y]\[x]: true]line:method[x0:integery0:integerx1:integery1:integer][[dx,dy]: @[abs x1 - x0, abs y1 - y0][x,y]: @[x0, y0]sx:(x0>x1)? -> neg 1 -> 1sy:(y0>y1)? -> neg 1 -> 1switchdx>dy[err:dx//2while[x<>x1][\setOnxyifnegative?err:<=err-dy->[y,err]: @[y + sy, err + dx]x:x+sx]][err:dy//2while[y<>y1][\setOnxyifnegative?err:<=err-dx->[x,err]: @[x + sx, err + dy]y:y+sy]]\setOnxy]string:method[][join.with:"\n"@["+"++(repeat"-"\width)++"+"join.with:"\n"map0..dec\height'y["|" ++ (join.with:"" map 0..dec \width 'x -> \grid\[dec \height-y]\[x] ? -> "@" -> "" ) ++ "|"]"+"++(repeat"-"\width)++"+"]]]; Create bitmap bitmap:to:bitmap@[1717]!; and... draw a diamond shapepoints:@[[18816][816168][16881][8118]]looppoints'p->bitmap\linep\0p\1p\2p\3printbitmap
- Output:
+-----------------+ | @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @| | @ @ | | @ @ | | @ @@ | | @ @ | | @ @ | | @ @ | | @ | | | +-----------------+
Assembly
16 bit Intel 8086\80486 Assembly for dos, see x86 assembly language. To run this code you will need to use Dos emulator.
.486 IDEAL ;--------------------------------------------- ; case: DeltaY is bigger than DeltaX ; input: p1X p1Y, ; p2X p2Y, ; Color -> variable ; output: line on the screen ;--------------------------------------------- Macro DrawLine2DDY p1X, p1Y, p2X, p2Y local l1, lp, nxt mov dx, 1 mov ax, [p1X] cmp ax, [p2X] jbe l1 neg dx ; turn delta to -1 l1: mov ax, [p2Y] shr ax, 1 ; div by 2 mov [TempW], ax mov ax, [p1X] mov [pointX], ax mov ax, [p1Y] mov [pointY], ax mov bx, [p2Y] sub bx, [p1Y] absolute bx mov cx, [p2X] sub cx, [p1X] absolute cx mov ax, [p2Y] lp: pusha call PIXEL popa inc [pointY] cmp [TempW], 0 jge nxt add [TempW], bx ; bx = (p2Y - p1Y) = deltay add [pointX], dx ; dx = delta nxt: sub [TempW], cx ; cx = abs(p2X - p1X) = daltax cmp [pointY], ax ; ax = p2Y jne lp call PIXEL ENDM DrawLine2DDY ;--------------------------------------------- ; case: DeltaX is bigger than DeltaY ; input: p1X p1Y, ; p2X p2Y, ; Color -> variable ; output: line on the screen ;--------------------------------------------- Macro DrawLine2DDX p1X, p1Y, p2X, p2Y local l1, lp, nxt mov dx, 1 mov ax, [p1Y] cmp ax, [p2Y] jbe l1 neg dx ; turn delta to -1 l1: mov ax, [p2X] shr ax, 1 ; div by 2 mov [TempW], ax mov ax, [p1X] mov [pointX], ax mov ax, [p1Y] mov [pointY], ax mov bx, [p2X] sub bx, [p1X] absolute bx mov cx, [p2Y] sub cx, [p1Y] absolute cx mov ax, [p2X] lp: pusha call PIXEL popa inc [pointX] cmp [TempW], 0 jge nxt add [TempW], bx ; bx = abs(p2X - p1X) = deltax add [pointY], dx ; dx = delta nxt: sub [TempW], cx ; cx = abs(p2Y - p1Y) = deltay cmp [pointX], ax ; ax = p2X jne lp call PIXEL ENDM DrawLine2DDX Macro absolute a local l1 cmp a, 0 jge l1 neg a l1: Endm MODEL small STACK 256 DATASEG TempW dw ? pointX dw ? pointY dw ? point1X dw ? point1Y dw ? point2X dw ? point2Y dw ? Color db ? CODESEG start: mov ax, @data mov ds, ax mov ax, 13h int 10h ; set graphic mode mov [Color], 61 mov [point1X], 300 mov [point2X], 6 mov [point1Y], 122 mov [point2Y], 88 call DrawLine2D mov ah, 00h int 16h exit: mov ax,03h int 10h ; set text mode mov ax, 4C00h int 21h ; procedures ;--------------------------------------------- ; input: point1X point1Y, ; point2X point2Y, ; Color ; output: line on the screen ;--------------------------------------------- PROC DrawLine2D mov cx, [point1X] sub cx, [point2X] absolute cx mov bx, [point1Y] sub bx, [point2Y] absolute bx cmp cx, bx jae DrawLine2Dp1 ; deltaX > deltaY mov ax, [point1X] mov bx, [point2X] mov cx, [point1Y] mov dx, [point2Y] cmp cx, dx jbe DrawLine2DpNxt1 ; point1Y <= point2Y xchg ax, bx xchg cx, dx DrawLine2DpNxt1: mov [point1X], ax mov [point2X], bx mov [point1Y], cx mov [point2Y], dx DrawLine2DDY point1X, point1Y, point2X, point2Y ret DrawLine2Dp1: mov ax, [point1X] mov bx, [point2X] mov cx, [point1Y] mov dx, [point2Y] cmp ax, bx jbe DrawLine2DpNxt2 ; point1X <= point2X xchg ax, bx xchg cx, dx DrawLine2DpNxt2: mov [point1X], ax mov [point2X], bx mov [point1Y], cx mov [point2Y], dx DrawLine2DDX point1X, point1Y, point2X, point2Y ret ENDP DrawLine2D ;----------------------------------------------- ; input: pointX pointY, ; Color ; output: point on the screen ;----------------------------------------------- PROC PIXEL mov bh,0h mov cx,[pointX] mov dx,[pointY] mov al,[Color] mov ah,0Ch int 10h ret ENDP PIXEL END start
ATS
AutoHotkey
Blue:=Color(0,0,255)White:=Color(255,255,255)Bitmap:=Bitmap(100,100,Blue) ;create a 100*100 blue bitmapLine(Bitmap,White,5,10,60,80) ;draw a white line from (5,10) to (60,80)Bitmap.Write("Line.ppm") ;write the bitmap to fileLine(ByRefBitmap,ByRefColor,PosX1,PosY1,PosX2,PosY2){DeltaX:=Abs(PosX2-PosX1),DeltaY:=-Abs(PosY2-PosY1) ;calculate deltasStepX:=((PosX1<PosX2)?1:-1),StepY:=((PosY1<PosY2)?1:-1) ;calculate stepsErrorValue:=DeltaX+DeltaY ;calculate error valueLoop ;loop over the pixel values{Bitmap[PosX1,PosX2]:=ColorIf(PosX1=PosX2&&PosY1=PosY2)BreakTemp1:=ErrorValue<<1,((Temp1>DeltaY)?(ErrorValue+=DeltaY,PosX1+=StepX):""),((Temp1<DeltaX)?(ErrorValue+=DeltaX,PosY1+=StepY):"") ;move forward}}
AutoIt
Local$var=drawBresenhamLine(2,3,2,6)FuncdrawBresenhamLine($iX0,$iY0,$iX1,$iY1)Local$iDx=Abs($iX1-$iX0)Local$iSx=$iX0<$iX1?1:-1Local$iDy=Abs($iY1-$iY0)Local$iSy=$iY0<$iY1?1:-1Local$iErr=($iDx>$iDy?$iDx:-$iDy)/2,$e2While$iX0<=$iX1ConsoleWrite("plot( $x="&$iX0&", $y="&$iY0&" )"&@LF)If($iX0=$iX1)And($iY0=$iY1)ThenReturn$e2=$iErrIf($e2>-$iDx)Then$iErr-=$iDy$iX0+=$iSxEndIfIf($e2<$iDy)Then$iErr+=$iDx$iY0+=$iSyEndIfWEndEndFunc ;==>drawBresenhamLine
bash
#! /bin/bashfunctionline{x0=$1y0=$2x1=$3y1=$4if((x0>x1))then((dx=x0-x1))((sx=-1))else((dx=x1-x0))((sx=1))fiif((y0>y1))then((dy=y0-y1))((sy=-1))else((dy=y1-y0))((sy=1))fiif((dx>dy))then((err=dx))else((err=-dy))fi((err/=2))((e2=0))while: doecho-en"\e[${y0};${x0}H#\e[K"((x0==x1&&y0==y1))&&return((e2=err))if((e2>-dx))then((err-=dy))((x0+=sx))fiif((e2<dy))then((err+=dx))((y0+=sy))fidone}# Draw a full screen diamondCOLS=$(tputcols)LINS=$(tputlines)LINS=$((LINS-1)) clear line$((COLS/2))1$((COLS/4))$((LINS/2)) line$((COLS/4))$((LINS/2))$((COLS/2))$LINS line$((COLS/2))$LINS$((COLS/4*3))$((LINS/2)) line$((COLS/4*3))$((LINS/2))$((COLS/2))1echo-e"\e[${LINS}H"
BASIC
1500REM===Drawaline.PortedfromCversion1510REMInputsareX1,Y1,X2,Y2:DestroysvalueofX1,Y11520DX=ABS(X2-X1):SX=-1:IFX1<X2THENSX=11530DY=ABS(Y2-Y1):SY=-1:IFY1<Y2THENSY=11540ER=-DY:IFDX>DYTHENER=DX1550ER=INT(ER/2)1560PLOTX1,Y1:REMThiscommandmaydifferdependingonBASICdialect1570IFX1=X2ANDY1=Y2THENRETURN1580E2=ER1590IFE2>-DXTHENER=ER-DY:X1=X1+SX1600IFE2<DYTHENER=ER+DX:Y1=Y1+SY1610GOTO1560
Batch File
@echo off setlocal enabledelayedexpansion setwidth=87 setheight=51 mode %width%,%height%set"grid="set/aresolution=height*widthfor/l%%i in(1,1,%resolution%)do(set"grid=!grid! ")call:line 1 1 5 5 call:line 9 30 60 7 call:line 9 30 60 50 call:line 52 50 32 1 echo:%grid%pause>nul exit:linesetx1=%1sety1=%2setx2=%3sety2=%4set/adx=x2-x1set/ady=y2-y1::Clipping done to avoid overflowif%dx%neq 0 set/ao=y1-(x1*dy/dx)if%x1%leq%x2%(if%x1%geq%width%goto:eofif%x2%lss 0 goto:eofif%x1%lss 0 (if%dx%neq 0 sety1=%o%setx1=0 )if%x2%geq%width%(set/ax2=width-1if%dx%neq 0 set/a"y2= x2 * dy / dx + o"))else(if%x2%geq%width%goto:eofif%x1%lss 0 goto:eofif%x2%lss 0 (if%dx%neq 0 sety2=%o%setx2=0 )if%x1%geq%width%(set/ax1=width-1if%dx%neq 0 set/a"y1= x1 * dy / dx + o"))if%y1%leq%y2%(if%y1%geq%height%goto:eofif%y2%lss 0 goto:eofif%y1%lss 0 (sety1=0 if%dx%neq 0 set/ax1=-o*dx/dy)if%y2%geq%height%(set/ay2=height-1if%dx%neq 0 set/a"x2= (y2 - o) * dx /dy"))else(if%y2%geq%height%goto:eofif%y1%lss 0 goto:eofif%y2%lss 0 (sety2=0 if%dx%neq 0 set/a"x2= - o * dx /dy")if%y1%geq%height%(set/ay1=height-1if%dx%neq 0 set/a"x1= (y1 - o) * dx /dy")):: Start of Bresenham's algorithmsetstepy=1 setstepx=1 set/adx=x2-x1set/ady=y2-y1if%dy%lss 0 set/a"dy=-dy","stepy=-1"if%dx%lss 0 set/a"dx=-dx","stepx=-1"set/a"dy <<= 1"set/a"dx <<= 1"if%dx%gtr%dy%(set/a"fraction=dy-(dx>>1)"set/a"cursor=y1*width + x1"for/l%%x in(%x1%,%stepx%,%x2%)do(set/acursorP=cursor+1for/f"tokens=1-2"%%g in("!cursor! !cursorP!")doset"grid=!grid:~0,%%g!Û!grid:~%%h!"if!fraction!geq 0 (set/ay1+=stepyset/acursor+=stepy*widthset/afraction-=dx)set/afraction+=dyset/acursor+=stepx))else(set/a"fraction=dx-(dy>>1)"set/a"cursor=y1*width + x1"for/l%%y in(%y1%,%stepy%,%y2%)do(set/acursorP=cursor+1for/f"tokens=1-2"%%g in("!cursor! !cursorP!")doset"grid=!grid:~0,%%g!Û!grid:~%%h!"if!fraction!geq 0 (set/ax1+=stepxset/acursor+=stepxset/afraction-=dy)set/afraction+=dxset/acursor+=width*stepy))goto:eof
BBC BASIC
Width%=200Height%=200REM Set window size:VDU23,22,Width%;Height%;8,16,16,128REM Draw lines:PROCbresenham(50,100,100,190,0,0,0)PROCbresenham(100,190,150,100,0,0,0)PROCbresenham(150,100,100,10,0,0,0)PROCbresenham(100,10,50,100,0,0,0)ENDDEFPROCbresenham(x1%,y1%,x2%,y2%,r%,g%,b%)LOCALdx%,dy%,sx%,sy%,edx%=ABS(x2%-x1%):sx%=SGN(x2%-x1%)dy%=ABS(y2%-y1%):sy%=SGN(y2%-y1%)IFdx%>dy%e=dx%/2ELSEe=dy%/2REPEATPROCsetpixel(x1%,y1%,r%,g%,b%)IFx1%=x2%IFy1%=y2%EXITREPEATIFdx%>dy%THENx1%+=sx%:e-=dy%:IFe<0e+=dx%:y1%+=sy%ELSEy1%+=sy%:e-=dx%:IFe<0e+=dy%:x1%+=sx%ENDIFUNTILFALSEENDPROCDEFPROCsetpixel(x%,y%,r%,g%,b%)COLOUR1,r%,g%,b%GCOL1LINEx%*2,y%*2,x%*2,y%*2ENDPROC
C
Instead of swaps in the initialisation use error calculation for both directions x and y simultaneously:
voidline(intx0,inty0,intx1,inty1){intdx=abs(x1-x0),sx=x0<x1?1:-1;intdy=abs(y1-y0),sy=y0<y1?1:-1;interr=(dx>dy?dx:-dy)/2,e2;for(;;){setPixel(x0,y0);if(x0==x1&&y0==y1)break;e2=err;if(e2>-dx){err-=dy;x0+=sx;}if(e2<dy){err+=dx;y0+=sy;}}}
C#
Port of the C version.
usingSystem;usingSystem.Drawing;usingSystem.Drawing.Imaging;staticclassProgram{staticvoidMain(){newBitmap(200,200).DrawLine(0,0,199,199,Color.Black).DrawLine(199,0,0,199,Color.Black).DrawLine(50,75,150,125,Color.Blue).DrawLine(150,75,50,125,Color.Blue).Save("line.png",ImageFormat.Png);}staticBitmapDrawLine(thisBitmapbitmap,intx0,inty0,intx1,inty1,Colorcolor){intdx=Math.Abs(x1-x0),sx=x0<x1?1:-1;intdy=Math.Abs(y1-y0),sy=y0<y1?1:-1;interr=(dx>dy?dx:-dy)/2,e2;for(;;){bitmap.SetPixel(x0,y0,color);if(x0==x1&&y0==y1)break;e2=err;if(e2>-dx){err-=dy;x0+=sx;}if(e2<dy){err+=dx;y0+=sy;}}returnbitmap;}}
C++
voidLine(floatx1,floaty1,floatx2,floaty2,constColor&color){// Bresenham's line algorithmconstboolsteep=(fabs(y2-y1)>fabs(x2-x1));if(steep){std::swap(x1,y1);std::swap(x2,y2);}if(x1>x2){std::swap(x1,x2);std::swap(y1,y2);}constfloatdx=x2-x1;constfloatdy=fabs(y2-y1);floaterror=dx/2.0f;constintystep=(y1<y2)?1:-1;inty=(int)y1;constintmaxX=(int)x2;for(intx=(int)x1;x<=maxX;x++){if(steep){SetPixel(y,x,color);}else{SetPixel(x,y,color);}error-=dy;if(error<0){y+=ystep;error+=dx;}}}
Clojure
(defn draw-line"Draw a line from x1,y1 to x2,y2 using Bresenham's, to a java BufferedImage in the colour of pixel."[bufferx1y1x2y2pixel](let [dist-x(Math/abs(- x1x2))dist-y(Math/abs(- y1y2))steep(> dist-ydist-x)](let [[x1y1x2y2](if steep[y1x1y2x2][x1y1x2y2])](let [[x1y1x2y2](if (> x1x2)[x2y2x1y1][x1y1x2y2])](let [delta-x(- x2x1)delta-y(Math/abs(- y1y2))y-step(if (< y1y2)1-1)](let [plot(if steep#(.setRGBbuffer(int %1)(int %2)pixel)#(.setRGBbuffer(int %2)(int %1)pixel))](loop [xx1yy1error(Math/floor(/ delta-x2))](plotxy)(if (< xx2); Rather then rebind error, test that it is less than delta-y rather than zero(if (< errordelta-y)(recur(inc x)(+ yy-step)(+ error(- delta-xdelta-y)))(recur(inc x)y(- errordelta-y)))))))))))
CoffeeScript
drawBresenhamLine=(x0, y0, x1, y1) ->dx=Math.abs(x1-x0)sx=ifx0<x1then1else-1dy=Math.abs(y1-y0)sy=ify0<y1then1else-1err=(ifdx>dythendxelse-dy)/2loopsetPixel(x0,y0)breakifx0==x1&&y0==y1e2=errife2>-dxerr-=dyx0+=sxife2<dyerr+=dxy0+=synull
Commodore BASIC
10rembresenhamlinealgorihm20remtranslatedfrompurebasic30x0=10:remstartxco-ord40y0=15:remstartyco-ord50x1=30:remendxco-ord60y1=20:remendyco-ord70se=0:rem0=steep1=!steep80ns=25:remnumsegments90dimpt(ns,2):rempointsinline100sc=1024:remstartofscreenmemory110sw=40:remscreenwidth120sh=25:remscreenheight130pc=42:remplotcharacter'*'140gosub1000150end1000remplotline1010ifabs(y1-y0)>abs(x1-x0)thense=1:tp=y0:y0=x0:x0=tp:tp=y1:y1=x1:x1=tp1020ifx0>x1thentp=x1:x1=x0:x0=tp:tp=y1:y1=y0:y0=tp1030dx=x1-x01040dy=abs(y1-y0)1050er=dx/21060y=y01070ys=-11080ify0<y1thenys=11090forx=x0tox11100ifse=1thenp0=y:p1=x:gosub2000:goto11201110p0=x:p1=y:gosub20001120er=er-dy1130ifer<0theny=y+ys:er=er+dx1140nextx1150return2000remplotindividualpoint2010remp0==plotpointx2020remp1==plotpointy2030sl=p0+(p1*sw)2040remmakesurewedontwritebeyondscreenmemory2050ifsl<(sw*sh)thenpokesc+sl,pc2060return
Common Lisp
(defundraw-line(bufferx1y1x2y2pixel)(declare(typergb-pixel-bufferbuffer))(declare(typeintegerx1y1x2y2))(declare(typergb-pixelpixel))(let*((dist-x(abs(-x1x2)))(dist-y(abs(-y1y2)))(steep(>dist-ydist-x)))(whensteep(psetfx1y1y1x1x2y2y2x2))(when(>x1x2)(psetfx1x2x2x1y1y2y2y1))(let*((delta-x(-x2x1))(delta-y(abs(-y1y2)))(error(floordelta-x2))(y-step(if(<y1y2)1-1))(yy1))(loop:forx:upfromx1:tox2:do(ifsteep(setf(rgb-pixelbufferxy)pixel)(setf(rgb-pixelbufferyx)pixel))(setferror(-errordelta-y))(when(<error0)(incfyy-step)(incferrordelta-x))))buffer))
D
This code uses the Image defined in Bitmap Task.
modulebitmap_bresenhams_line_algorithm;importstd.algorithm,std.math,bitmap;voiddrawLine(Color)(Image!Colorimg,size_tx1,size_ty1,insize_tx2,insize_ty2,inColorcolor)purenothrow@nogc{immutableintdx=x2-x1;immutableintix=(dx>0)-(dx<0);immutablesize_tdx2=abs(dx)*2;intdy=y2-y1;immutableintiy=(dy>0)-(dy<0);immutablesize_tdy2=abs(dy)*2;img[x1,y1]=color;if(dx2>=dy2){interror=dy2-(dx2/2);while(x1!=x2){if(error>=0&&(error||(ix>0))){error-=dx2;y1+=iy;}error+=dy2;x1+=ix;img[x1,y1]=color;}}else{interror=dx2-(dy2/2);while(y1!=y2){if(error>=0&&(error||(iy>0))){error-=dy2;x1+=ix;}error+=dx2;y1+=iy;img[x1,y1]=color;}}}version(bitmap_bresenhams_line_algorithm_main){voidmain(){autoimg=newImage!RGB(25,22);img.drawLine(5,5,15,20,RGB.white);img.drawLine(3,20,10,12,RGB.white);img.textualShow();}}
To run the demo code compile with -version=bitmap_bresenhams_line_algorithm_main
.
- Output:
######################### ######################### ######################### ######################### ######################### #####.################### ######.################## ######.################## #######.################# ########.################ ########.################ #########.############### ##########.############## #########..############## ########.##.############# #######.####.############ ######.#####.############ ######.######.########### #####.########.########## ####.#########.########## ###.###########.######### #########################
Delphi
proceduredrawLine(bitmap:TBitmap;xStart,yStart,xEnd,yEnd:integer;color:TAlphaColor);// Bresenham's Line Algorithm. Byte, March 1988, pp. 249-253.// Modified from http://www.efg2.com/Lab/Library/Delphi/Graphics/Bresenham.txt and tested.vara,b:integer;// displacements in x and yd:integer;// decision variablediag_inc:integer;// d's increment for diagonal stepsdx_diag:integer;// diagonal x step for next pixeldx_nondiag:integer;// nondiagonal x step for next pixeldy_diag:integer;// diagonal y step for next pixeldy_nondiag:integer;// nondiagonal y step for next pixeli:integer;// loop indexnondiag_inc:integer;// d's increment for nondiagonal stepsswap:integer;// temporary variable for swapx,y:integer;// current x and y coordinatesbeginx:=xStart;// line starting point}y:=yStart;// Determine drawing direction and step to the next pixel.a:=xEnd-xStart;// difference in x dimensionb:=yEnd-yStart;// difference in y dimension// Determine whether end point lies to right or left of start point.ifa<0then// drawing towards smaller x values?begina:=-a;// make 'a' positivedx_diag:=-1endelsedx_diag:=1;// Determine whether end point lies above or below start point.ifb<0then// drawing towards smaller x values?beginb:=-b;// make 'a' positivedy_diag:=-1endelsedy_diag:=1;// Identify octant containing end point.ifa<bthenbeginswap:=a;a:=b;b:=swap;dx_nondiag:=0;dy_nondiag:=dy_diagendelsebegindx_nondiag:=dx_diag;dy_nondiag:=0end;d:=b+b-a;// initial value for d is 2*b - anondiag_inc:=b+b;// set initial d increment valuesdiag_inc:=b+b-a-a;fori:=0toadobegin/// draw the a+1 pixelsdrawPixel(bitmap,x,y,color);ifd<0then// is midpoint above the line?begin// step nondiagonallyx:=x+dx_nondiag;y:=y+dy_nondiag;d:=d+nondiag_inc// update decision variableendelsebegin// midpoint is above the line; step diagonally}x:=x+dx_diag;y:=y+dy_diag;d:=d+diag_incend;end;end;
E
def swap(&left, &right) { # From [[Generic swap]] def t := left left := right right := t } def drawLine(image, var x0, var y0, var x1, var y1, color) { def steep := (y1 - y0).abs() > (x1 - x0).abs() if (steep) { swap(&x0, &y0) swap(&x1, &y1) } if (x0 > x1) { swap(&x0, &x1) swap(&y0, &y1) } def deltax := x1 - x0 def deltay := (y1 - y0).abs() def ystep := if (y0 < y1) { 1 } else { -1 } var error := deltax // 2 var y := y0 for x in x0..x1 { if (steep) { image[y, x] := color } else { image[x, y] := color } error -= deltay if (error < 0) { y += ystep error += deltax } } }
def i := makeImage(5, 20) drawLine(i, 1, 1, 3, 18, makeColor.fromFloat(0,1,1)) i.writePPM(<import:java.io.makeFileOutputStream>(<file:~/Desktop/Bresenham.ppm>))
EasyLang
proc pset x y . move x / 4 y / 4 rect 0.25 0.25 . proc drawline x0 y0 x1 y1 . dx = abs (x1 - x0) sx = -1 if x0 < x1 sx = 1 . dy = abs (y1 - y0) sy = -1 if y0 < y1 sy = 1 . err = -dy div 2 if dx > dy err = dx div 2 . repeat pset x0 y0 until x0 = x1 and y0 = y1 e2 = err if e2 > -dx err -= dy x0 += sx . if e2 < dy err += dx y0 += sy . . . drawline 200 10 100 200 drawline 100 200 200 390 drawline 200 390 300 200 drawline 300 200 200 10
Elm
-- Brensenham Line AlgorithmtypealiasPosition={x:Int,y:Int}typealiasBresenhamStatics={finish:Position,sx:Int,sy:Int,dx:Float,dy:Float}line:Position->Position->ListPositionlinepq=letdx=(toFloat<<abs)(q.x-p.x)dy=(toFloat<<abs)(q.y-p.y)sx=ifp.x<q.xthen1else-1sy=ifp.y<q.ythen1else-1error=(ifdx>dythendxelse-dy)/2statics=BresenhamStaticsqsxsydxdyinbresenhamLineLoopstaticserrorp[]bresenhamLineLoop:BresenhamStatics->Float->Position->ListPosition->ListPositionbresenhamLineLoopstaticserrorppositions=letpositions_=p::positions{sx,sy,dx,dy,finish}=staticsinif(p.x==finish.x)&&(p.y==finish.y)thenpositions_elselet(dErrX,x)=iferror>-dxthen(-dy,sx+p.x)else(0,p.x)(dErrY,y)=iferror<dythen(dx,sy+p.y)else(0,p.y)error_=error+dErrX+dErrYinbresenhamLineLoopstaticserror_(Positionxy)positions_
Erlang
build_path({Sx,Sy},{Tx,Ty})->ifTx<Sx->StepX=-1;true->StepX=1end,ifTy<Sy->StepY=-1;true->StepY=1end,Dx=abs((Tx-Sx)*2),Dy=abs((Ty-Sy)*2),ifDy>Dx->Path=through_y({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},Dx*2-Dy,[]);true->Path=through_x({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},Dy*2-Dx,[])end,lists:reverse(Path).through_x({Tx,_},{Tx,_},_,_,_,P)->P;through_x({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},F0,P)whenF0>=0->Ny=Sy+StepY,F1=F0-Dx,Nx=Sx+StepX,F2=F1+Dy,through_x({Nx,Ny},{Tx,Ty},{StepX,StepY},{Dx,Dy},F2,[{Nx,Ny}|P]);through_x({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},F0,P)whenF0<0->Ny=Sy,Nx=Sx+StepX,F2=F0+Dy,through_x({Nx,Ny},{Tx,Ty},{StepX,StepY},{Dx,Dy},F2,[{Nx,Ny}|P]).through_y({_,Ty},{_,Ty},_,_,_,P)->P;through_y({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},F0,P)whenF0>=0->Nx=Sx+StepX,F1=F0-Dy,Ny=Sy+StepY,F2=F1+Dx,through_y({Nx,Ny},{Tx,Ty},{StepX,StepY},{Dx,Dy},F2,[{Nx,Ny}|P]);through_y({Sx,Sy},{Tx,Ty},{StepX,StepY},{Dx,Dy},F0,P)whenF0<0->Nx=Sx,Ny=Sy+StepY,F2=F0+Dx,through_y({Nx,Ny},{Tx,Ty},{StepX,StepY},{Dx,Dy},F2,[{Nx,Ny}|P]).
OR
line({X0,Y0},{X1,Y1})->SX=step(X0,X1),SY=step(Y0,Y1),DX=abs(X1-X0),DY=abs(Y1-Y0),Err=DX-DY,line({X0,Y0},{X1,Y1},{SX,SY},{DX,DY},Err,[]).line({X1,Y1},{X1,Y1},_,_,_,Acc)->lists:reverse([{X1,Y1}|Acc]);line({X,Y},{X1,Y1},{SX,SY},{DX,DY},Err,Acc)->DE=2*Err,{X0,Err0}=next_x(X,SX,DY,Err,DE),{Y0,Err1}=next_y(Y,SY,DX,Err0,DE),line({X0,Y0},{X1,Y1},{SX,SY},{DX,DY},Err1,[{X,Y}|Acc]).step(P0,P1)whenP0<P1->1;step(_,_)->-1.next_x(X,SX,DY,E,DE)whenDE>-DY->{X+SX,E-DY};next_x(X,_SX,_DY,E,_DE)->{X,E}.next_y(Y,SY,DX,E,DE)whenDE<DX->{Y+SY,E+DX};next_y(Y,_SY,_DX,E,_DE)->{Y,E}.
ERRE
PROGRAM BRESENHAM !$INCLUDE="PC.LIB" PROCEDURE BRESENHAM ! === Draw a line using graphic coordinates ! Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1 dx=ABS(x2-x1) sx=-1 IF x1<x2 THEN sx=1 dy=ABS(y2-y1) sy=-1 IF y1<y2 THEN sy=1 er=-dy IF dx>dy THEN er=dx er=INT(er/2) LOOP PSET(x1,y1,1) EXIT IF x1=x2 AND y1=y2 e2=er IF e2>-dx THEN er=er-dy x1=x1+sx IF e2<dy THEN er=er+dx y1=y1+sy END LOOP END PROCEDURE BEGIN SCREEN(2) INPUT(x1,y1,x2,y2) BRESENHAM GET(A$) SCREEN(0) END PROGRAM
Euphoria
include std/console.e include std/graphics.e include std/math.e -- the new_image function and related code in the 25 or so -- lines below are from http://rosettacode.org/wiki/Basic_bitmap_storage#Euphoria -- as of friday, march 2, 2012 -- Some color constants: constant black = #000000, white = #FFFFFF, red = #FF0000, green = #00FF00, blue = #0000FF -- Create new image filled with some color function new_image(integer width, integer height, atom fill_color) return repeat(repeat(fill_color,height),width) end function --grid used for drawing lines in this program sequence screenData = new_image(16,16,black) --the line algorithm function bresLine(sequence screenData, integer x0, integer y0, integer x1, integer y1, integer color) integer deltaX = abs(x1 - x0), deltaY = abs(y1 - y0) integer stepX, stepY, lineError, error2 if x0 < x1 then stepX = 1 else stepX = -1 end if if y0 < y1 then stepY = 1 else stepY = -1 end if if deltaX > deltaY then lineError = deltaX else lineError = -deltaY end if lineError = round(lineError / 2, 1) while 1 do screenData[x0][y0] = color if (x0 = x1 and y0 = y1) then exit end if error2 = lineError if error2 > -deltaX then lineError -= deltaY x0 += stepX end if if error2 < deltaY then lineError += deltaX y0 += stepY end if end while return screenData -- return modified version of the screenData sequence end function --prevents console output wrapping to next line if it is too big for the screen wrap(0) --outer diamond screenData = bresLine(screenData,8,1,16,8,white) screenData = bresLine(screenData,16,8,8,16,white) screenData = bresLine(screenData,8,16,1,8,white) screenData = bresLine(screenData,1,8,8,1,white) --inner diamond screenData = bresLine(screenData,8,4,12,8,white) screenData = bresLine(screenData,12,8,8,12,white) screenData = bresLine(screenData,8,12,4,8,white) screenData = bresLine(screenData,4,8,8,4,white) -- center lines drawing from left to right, and the next from right to left. screenData = bresLine(screenData,7,7,9,7,white) screenData = bresLine(screenData,9,9,7,9,white) --center dot screenData = bresLine(screenData,8,8,8,8,white) --print to the standard console output for i = 1 to 16 do puts(1,"\n") for j = 1 to 16 do if screenData[j][i] = black then printf(1, "%s", ".") else printf(1, "%s", "#") end if end for end for puts(1,"\n\n") any_key() --/* --output was edited to replace the color's hex digits for clearer output graphics. --to output all the hex digits, use printf(1,"%06x", screenData[j][i]) --to output 'shortened' hex digits, use : --printf(1, "%x", ( abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) - 1 ) ) --and --printf(1,"%x", abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) ) -- --,respectively in the last if check. --*/
Output:
.......#........ ......#.#....... .....#...#...... ....#..#..##.... ...#..#.#...#... ..#..#...#...#.. .#..#.###.#...#. #..#...#...#...# .#..#.###.#...#. ..#..#...#...#.. ...#..#.#...#... ....#..#...#.... ....#.....#..... .....#...#...... ......#.#....... .......#........ Press Any Key to continue...
F#
letinlinebresenhamfill(x0,y0)(x1,y1)=letsteep=abs(y1-y0)>abs(x1-x0)letx0,y0,x1,y1=ifsteeptheny0,x0,y1,x1elsex0,y0,x1,y1letx0,y0,x1,y1=ifx0>x1thenx1,y1,x0,y0elsex0,y0,x1,y1letdx,dy=x1-x0,abs(y1-y0)lets=ify0<y1then1else-1letrecloopexy=ifx<=x1thenifsteepthenfillyxelsefillxyife<dythenloop(e-dy+dx)(x+1)(y+s)elseloop(e-dy)(x+1)yloop(dx/2)x0y0
The following program tests the above bresenham function by drawing 100 lines into an image and visualizing the result using
:
openSystem.WindowsopenSystem.Windows.Media.Imaging[<System.STAThread>]doletrand=System.Random()letn=256letpixel=Array.create(n*n)0uyletrand=System.Random().Nextfor_in1..100dobresenham(funxy->pixel.[x+y*n]<-255uy)(randn,randn)(randn,randn)letimage=Controls.Image(Stretch=Media.Stretch.Uniform)letformat=Media.PixelFormats.Gray8image.Source<-BitmapSource.Create(n,n,1.0,1.0,format,null,pixel,n)Window(Content=image,Title="Bresenham's line algorithm")|>(Application()).Run|>ignore
Factor
A very ugly imperative implementation similar to the wikipedia pseudocode..
USING:accessorsarrayskernellocalsmathmath.functionsmath.rangesmath.vectorsrosettacode.raster.displayrosettacode.raster.storagesequencesui.gadgets;IN:rosettacode.raster.line::line-points(pt1pt2--points)pt1first2:>y0!:>x0! pt2first2:>y1!:>x1! y1y0-absx1x0-abs>:>steep steep[y0x0y0!x0!y1x1y1!x1!]whenx0x1>[ x0x1x0!x1! y0y1y0!y1! ]whenx1x0-:>deltax y1y0-abs:>deltay 0 :>current-error! deltaydeltax/abs:>deltaerr 0 :>ystep! y0:>y! y0y1<[1 ystep!][-1 ystep!]ifx0x11 <range>[ ysteep[swap]when2arraycurrent-errordeltaerr+current-error!current-error0.5 >=[ ystepy+y! current-error1 -current-error! ]when]{}map-as;! Needs rosettacode.raster.storage for the set-pixel function and to create the image:draw-line({R,G,B}pt1pt2image--)[line-points]dip[set-pixel]currywitheach;
FBSL
1. In FBSL, successive calls to one and the same subprocedure may be concatenated to a series of argument sets as in Sub Rhombus() below.
2. In FBSL, BASIC-style logical AND and OR operators are "inclusive", i.e. they always evaluate the both of their conditions. C-style logical ANDALSO and ORELSE operators are "exclusive". ANDALSO evaluates the second condition if, and only if, its first condition is TRUE as in Sub Bresenham() below. ORELSE evaluates its second condition if, and only if, its first condition is FALSE.
Using pure FBSL's built-in graphics functions:
#DEFINEWM_LBUTTONDOWN513#DEFINEWM_CLOSE16FBSLSETTEXT(ME,"Bresenham")' Set form captionFBSLSETFORMCOLOR(ME,RGB(0,255,255))' Cyan: set persistent background colorDRAWWIDTH(5)' Adjust point sizeFBSL.GETDC(ME)' Use volatile FBSL.GETDC below to avoid extra assignmentsRESIZE(ME,0,0,200,235)CENTER(ME)SHOW(ME)BEGINEVENTSSELECT CASECBMSGCASEWM_LBUTTONDOWN:Rhombus()' DrawCASEWM_CLOSE:FBSL.RELEASEDC(ME,FBSL.GETDC)' Clean upENDSELECTENDEVENTSSUBRhombus()Bresenham(50,100,100,190)(100,190,150,100)(150,100,100,10)(100,10,50,100)SUBBresenham(x0,y0,x1,y1)DIMdx=ABS(x0-x1),sx=SGN(x0-x1)DIMdy=ABS(y0-y1),sy=SGN(y0-y1)DIMtmp,er=IIF(dx>dy,dx,-dy)/2WHILENOT(x0=x1ANDALSOy0=y1)PSET(FBSL.GETDC,x0,y0,&HFF)' Red: Windows stores colors in BGR ordertmp=erIFtmp>-dxTHEN:er=er-dy:x0=x0+sx:ENDIFIFtmp<+dyTHEN:er=er+dx:y0=y0+sy:ENDIFWENDENDSUBENDSUB
Forth
defersteep\ noop or swapdeferystep\ 1+ or 1-:line( x0 y0 x1 y1 color bmp -- ){colorbmp}rotswap( x0 x1 y0 y1 )2dup-abs>r2over-absr><if[']swap\ swap use of x and yelse2swap[']noopthenissteep( y0 y1 x0 x1 )2dup>ifswap2swapswap\ ensure x1 > x0else2swapthen( x0 x1 y0 y1 )2dup>if[']1-else[']1+thenisystepover-abs{ydeltay}swap2dup-dup{deltax}2/rot1+rot( error x1+1 x0 )docoloriysteepbmpb!deltay-dup0<ifyysteptoydeltax+thenloopdrop;55bitmapvaluetest0testbfill1041redtestline4134redtestline3403redtestline0310redtestlinetestbshowcr************ok
Fortran
module RCImagePrimitiveuse RCImageBasicimplicit none type pointinteger::x,yend type pointprivate::swapcoordcontains subroutine swapcoord(p1,p2)integer,intent(inout)::p1,p2integer::tt=p2p2=p1p1=tend subroutine swapcoordsubroutine draw_line(img,from,to,color)type(rgbimage),intent(inout)::imgtype(point),intent(in)::from,totype(rgb),intent(in)::colortype(point)::rfrom,rtointeger::dx,dy,error,ystep,x,ylogical::steeprfrom=fromrto=tosteep=(abs(rto%y-rfrom%y)>abs(rto%x-rfrom%x))if(steep)then call swapcoord(rfrom%x,rfrom%y)call swapcoord(rto%x,rto%y)end if if(rfrom%x>rto%x)then call swapcoord(rfrom%x,rto%x)call swapcoord(rfrom%y,rto%y)end ifdx=rto%x-rfrom%xdy=abs(rto%y-rfrom%y)error=dx/2y=rfrom%yif(rfrom%y<rto%y)thenystep=1elseystep=-1end if do x=rfrom%x,rto%xif(steep)then call put_pixel(img,y,x,color)else call put_pixel(img,x,y,color)end iferror=error-dyif(error<0)theny=y+ysteperror=error+dxend if end do end subroutine draw_lineend module RCImagePrimitive
Usage example:
program BasicImageTestsuse RCImageBasicuse RCImageIOuse RCImagePrimitiveimplicit none type(rgbimage)::animageinteger::x,ycall alloc_img(animage,200,200)call fill_img(animage,rgb(255,255,255))call draw_line(animage,point(0,0),point(199,199),rgb(0,0,0))do y=0,219,20call draw_line(animage,point(0,0),point(199,y),&rgb(0,0,0))end do open(unit=10,file='outputimage.ppm',status='new')call output_ppm(10,animage)close(10)call free_img(animage)end program BasicImageTests
FreeBASIC
' version 16-09-2015' compile with: fbc -s console' OR compile with: fbc -s gui' Ported from the C versionSubBr_line(x0AsInteger,y0AsInteger,x1AsInteger,y1AsInteger,ColAsInteger=&HFFFFFF)DimAsIntegerdx=Abs(x1-x0),dy=Abs(y1-y0)DimAsIntegersx=IIf(x0<x1,1,-1)DimAsIntegersy=IIf(y0<y1,1,-1)DimAsIntegerer=IIf(dx>dy,dx,-dy)\2,e2DoPSet(x0,y0),colIf(x0=x1)And(y0=y1)ThenExitDoe2=erIfe2>-dxThenEr-=dy:x0+=sxIfe2<dyThenEr+=dx:y0+=syLoopEndSub' ------=< MAIN >=------DimAsDoublex0,y0,x1,y1ScreenRes400,400,32WindowTitle" Press key to end demo"RandomizeTimerDoClsForaAsInteger=1To20Br_line(Rnd*380+10,Rnd*380+10,Rnd*380+10,Rnd*380+10,Rnd*&hFFFFFF)NextSleep2000LoopUntilInKey<>""' loop until a key is pressedEnd
Go
packageraster// Line draws line by Bresenham's algorithm.func(b*Bitmap)Line(x0,y0,x1,y1int,pPixel){// implemented straight from WP pseudocodedx:=x1-x0ifdx<0{dx=-dx}dy:=y1-y0ifdy<0{dy=-dy}varsx,syintifx0<x1{sx=1}else{sx=-1}ify0<y1{sy=1}else{sy=-1}err:=dx-dyfor{b.SetPx(x0,y0,p)ifx0==x1&&y0==y1{break}e2:=2*errife2>-dy{err-=dyx0+=sx}ife2<dx{err+=dxy0+=sy}}}func(b*Bitmap)LineRgb(x0,y0,x1,y1int,cRgb){b.Line(x0,y0,x1,y1,c.Pixel())}
A demonstration program:
packagemain// Files required to build supporting package raster are found in:// * This task (immediately above)// * Bitmap// * Write a PPM fileimport("raster""fmt")funcmain(){b:=raster.NewBitmap(400,300)b.FillRgb(0xdfefff)blue:=raster.Rgb(0x8fcfff)b.LineRgb(7,12,307,122,blue)b.LineRgb(177,12,127,222,blue)err:=b.WritePpmFile("bresenham.ppm")iferr!=nil{fmt.Println(err)}}
Haskell
moduleBitmap.Line(line)whereimportBitmapimportControl.MonadimportControl.Monad.STimportqualifiedData.STRefvar=Data.STRef.newSTRefget=Data.STRef.readSTRefmutate=Data.STRef.modifySTRefline::Colorc=>Imagesc->Pixel->Pixel->c->STs()linei(Pixel(xa,ya))(Pixel(xb,yb))c=doyV<-vary1errorV<-var$deltax`div`2forM_[x1..x2](\x->doy<-getyVsetPixi(Pixel$ifsteepthen(y,x)else(x,y))cmutateerrorV$subtractdeltayerror<-geterrorVwhen(error<0)(domutateyV(+ystep)mutateerrorV(+deltax)))wheresteep=abs(yb-ya)>abs(xb-xa)(xa',ya',xb',yb')=ifsteepthen(ya,xa,yb,xb)else(xa,ya,xb,yb)(x1,y1,x2,y2)=ifxa'>xb'then(xb',yb',xa',ya')else(xa',ya',xb',yb')deltax=x2-x1deltay=abs$y2-y1ystep=ify1<y2then1else-1
J
Solution:
Using definitions from Basic bitmap storage.
thru=:<./+-~i.@+_1^>NB. integers from x through yNB.*getBresenhamLine v Returns points for a line given start and end pointsNB. y is: y0 x0 ,: y1 x1getBresenhamLine=:monaddefinesteep=.([:</|@-~/)ypoints=.|."1^:steepyslope=.%~/-~/pointsypts=.thru/{."1pointsxpts=.({:+0.5<.@:+slope*ypts-{.){.points|."1^:steepypts,.xpts)NB.*drawLines v Draws lines (x) on image (y)NB. x is: 2-item list (start and end points) ; (color)drawLines=:(1&{::;~[:;[:<@getBresenhamLine"2(0&{::))@[setPixels]
Example Usage:
myimg=:02550makeRGB2032NB. 32 by 20 green imagemyimg=:((11,:511);25500)drawLinesmyimgNB. draw red line from xy point 1 1 to 11 5NB. Works for lists of 2 by 2 arrays each defining a line's start and end point.Diamond=:_2]\_2]\95515,515925,9251315,131595Square=:_2]\_2]\55525,5251325,1325135,13555viewRGBmyimg=:(Diamond;25500)drawLinesmyimgNB. draw 4 red lines to form a diamond viewRGBmyimg=:(Square;00255)drawLinesmyimgNB. draw 4 blue lines to form a squareviewRGB(Diamond;25500)drawLines(Square;00255)drawLinesmyimg
Java
importjava.awt.Color;importjava.awt.Dimension;importjava.awt.Graphics;importjavax.swing.JFrame;importjavax.swing.JPanel;importjavax.swing.SwingUtilities;importjavax.swing.WindowConstants;publicclassBresenham{publicstaticvoidmain(String[]args){SwingUtilities.invokeLater(Bresenham::run);}privatestaticvoidrun(){JFramef=newJFrame();f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);f.setTitle("Bresenham");f.getContentPane().add(newBresenhamPanel());f.pack();f.setLocationRelativeTo(null);f.setVisible(true);}}classBresenhamPanelextendsJPanel{privatefinalintpixelSize=10;BresenhamPanel(){setPreferredSize(newDimension(600,500));setBackground(Color.WHITE);}@OverridepublicvoidpaintComponent(Graphicsg){super.paintComponent(g);intw=(getWidth()-1)/pixelSize;inth=(getHeight()-1)/pixelSize;intmaxX=(w-1)/2;intmaxY=(h-1)/2;intx1=-maxX,x2=maxX*-2/3,x3=maxX*2/3,x4=maxX;inty1=-maxY,y2=maxY*-2/3,y3=maxY*2/3,y4=maxY;drawLine(g,0,0,x3,y1);// NNEdrawLine(g,0,0,x4,y2);// ENEdrawLine(g,0,0,x4,y3);// ESEdrawLine(g,0,0,x3,y4);// SSEdrawLine(g,0,0,x2,y4);// SSWdrawLine(g,0,0,x1,y3);// WSWdrawLine(g,0,0,x1,y2);// WNWdrawLine(g,0,0,x2,y1);// NNW}privatevoidplot(Graphicsg,intx,inty){intw=(getWidth()-1)/pixelSize;inth=(getHeight()-1)/pixelSize;intmaxX=(w-1)/2;intmaxY=(h-1)/2;intborderX=getWidth()-((2*maxX+1)*pixelSize+1);intborderY=getHeight()-((2*maxY+1)*pixelSize+1);intleft=(x+maxX)*pixelSize+borderX/2;inttop=(y+maxY)*pixelSize+borderY/2;g.setColor(Color.black);g.drawOval(left,top,pixelSize,pixelSize);}privatevoiddrawLine(Graphicsg,intx1,inty1,intx2,inty2){// delta of exact value and rounded value of the dependent variableintd=0;intdx=Math.abs(x2-x1);intdy=Math.abs(y2-y1);intdx2=2*dx;// slope scaling factors tointdy2=2*dy;// avoid floating pointintix=x1<x2?1:-1;// increment directionintiy=y1<y2?1:-1;intx=x1;inty=y1;if(dx>=dy){while(true){plot(g,x,y);if(x==x2)break;x+=ix;d+=dy2;if(d>dx){y+=iy;d-=dx2;}}}else{while(true){plot(g,x,y);if(y==y2)break;y+=iy;d+=dx2;if(d>dy){x+=ix;d-=dy2;}}}}}
JavaScript
Instead of swaps in the initialisation use error calculation for both directions x and y simultaneously:
functionbline(x0,y0,x1,y1){vardx=Math.abs(x1-x0),sx=x0<x1?1:-1;vardy=Math.abs(y1-y0),sy=y0<y1?1:-1;varerr=(dx>dy?dx:-dy)/2;while(true){setPixel(x0,y0);if(x0===x1&&y0===y1)break;vare2=err;if(e2>-dx){err-=dy;x0+=sx;}if(e2<dy){err+=dx;y0+=sy;}}}
Julia
functiondrawline!(img::Matrix{T},x0::Int,y0::Int,x1::Int,y1::Int,col::T)whereTδx=abs(x1-x0)δy=abs(y1-y0)δe=abs(δy/δx)er=0.0y=y0forxinx0:x1img[x,y]=coler+=δeifer>0.5y+=1er-=1.0endendreturnimgendusingImagesimg=fill(Gray(255.0),5,5);println("\nImage:")display(img);println()drawline!(img,1,1,5,5,Gray(0.0));println("\nModified image:")display(img);println()
- Output:
Image: 5×5 Array{Gray{Float64},2}: Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Modified image: 5×5 Array{Gray{Float64},2}: Gray{Float64}(0.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(0.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(0.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(0.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(255.0) Gray{Float64}(0.0)
ksh
functionline{typesetx0=$1y0=$2x1=$3y1=$4if((x0>x1))then((dx=x0-x1));((sx=-1))else((dx=x1-x0));((sx=1))fiif((y0>y1))then((dy=y0-y1));((sy=-1))else((dy=y1-y0));((sy=1))fiif((dx>dy))then((err=dx))else((err=-dy))fi((err/=2));((e2=0))while: doecho$x0$y0((x0==x1&&y0==y1))&&return((e2=err))((e2>-dx))&&{((err-=dy));((x0+=sx))}((e2<dy))&&{((err+=dx));((y0+=sy))}done}
Output from the statement:
line 0 0 3 4
(which could be piped to another program)
0 0 1 1 1 2 2 3 3 4
Lua
------------------------------------------------- Bitmap replacement-- (why? current Lua impl lacks a "set" method)-----------------------------------------------localBitmap={new=function(self,width,height)localinstance=setmetatable({width=width,height=height},self)instance:alloc()returninstanceend,alloc=function(self)self.pixels={}fory=1,self.heightdoself.pixels[y]={}forx=1,self.widthdoself.pixels[y][x]=0x00000000endendend,clear=function(self,c)fory=1,self.heightdoforx=1,self.widthdoself.pixels[y][x]=cor0x00000000endendend,get=function(self,x,y)x,y=math.floor(x+1),math.floor(y+1)if((x>=1)and(x<=self.width)and(y>=1)and(y<=self.height))thenreturnself.pixels[y][x]elsereturnnilendend,set=function(self,x,y,c)x,y=math.floor(x+1),math.floor(y+1)if((x>=1)and(x<=self.width)and(y>=1)and(y<=self.height))thenself.pixels[y][x]=cor0x00000000endend,}Bitmap.__index=Bitmapsetmetatable(Bitmap,{__call=function(t,...)returnt:new(...)end})-------------------------------- Bresenham's Line Algorithm:------------------------------Bitmap.line=function(self,x1,y1,x2,y2,c)localdx,sx=math.abs(x2-x1),x1<x2and1or-1localdy,sy=math.abs(y2-y1),y1<y2and1or-1localerr=math.floor((dx>dyanddxor-dy)/2)while(true)doself:set(x1,y1,cor0xFFFFFFFF)if(x1==x2andy1==y2)thenbreakendif(err>-dx)thenerr,x1=err-dy,x1+sxif(x1==x2andy1==y2)thenself:set(x1,y1,cor0xFFFFFFFF)breakendendif(err<dy)thenerr,y1=err+dx,y1+syendendend---------- Demo:--------Bitmap.render=function(self,charmap)fory=1,self.heightdolocalrowtab={}forx=1,self.widthdorowtab[x]=charmap[self.pixels[y][x]]endprint(table.concat(rowtab))endendlocalbitmap=Bitmap(61,21)bitmap:clear()bitmap:line(0,10,30,0)bitmap:line(30,0,60,10)bitmap:line(60,10,30,20)bitmap:line(30,20,0,10)bitmap:render({[0x000000]='.',[0xFFFFFFFF]='X'})
- Output:
.............................XXX.......................................................XXX...XXX.......................... .......................XXX.........XXX....................... ....................XXX...............XXX.................... .................XXX.....................XXX................. ..............XXX...........................XXX.............. ...........XXX.................................XXX........... ........XXX.......................................XXX........ .....XXX.............................................XXX..... ..XXX...................................................XXX.. XX.........................................................XX ..XXX...................................................XXX.. .....XXX.............................................XXX..... ........XXX.......................................XXX........ ...........XXX.................................XXX........... ..............XXX...........................XXX.............. .................XXX.....................XXX................. ....................XXX...............XXX.................... .......................XXX.........XXX....................... ..........................XXX...XXX.......................... .............................XXX.............................
M2000 Interpreter
' using Twips' twipsX is 15 twips. So for 96 dpi, we have 1440/96=15 twips/pixelModuleBresenham_s_line_algorithm{ModuleBr_line(x0AsLong,y0AsLong,x1AsLong,y1AsLong,Col=15){Longdx=Abs(x1-x0),dy=Abs(y1-y0)Longsx=If(x0<x1->TWIPSX,-TWIPSX)Longsy=If(y0<y1->TWIPSY,-TWIPSY)Longer=If(dx>dy->dx,-dy)div2,e2DoPSetcol,x0,y0Ifabs(x0-x1)<=TWIPSXAndabs(y0-y1)<=TWIPSYThenExite2=erIfe2>-dxThenEr-=dy:x0+=sxIfe2<dyThenEr+=dx:y0+=syAlways}cls,0Br_linescale.x*.2,scale.y*.2,scale.x*.8,scale.y*.8,#FFbb77}Bresenham_s_line_algorithm
Maple
SegmentBresenham := proc (img, x0, y0, x1, y1) local deltax, deltay, x, y, ystep, steep, err, img2, x02, y02, x12, y12; x02, x12, y02, y12 := y0, y1, x0, x1; steep := abs(x12 - x02) < abs(y12 - y02); img2 := copy(img); if steep then x02, y02 := y02, x02; x12, y12 := y12, x12; end if; if x12 < x02 then x02, x12 := x12, x02; y02, y12 := y12, y02; end if; deltax := x12 - x02; deltay := abs(y12 - y02); err := deltax / 2; y := y02; if y02 < y12 then ystep := 1 else ystep := -1 end if; for x from x02 to x12 do if steep then img2[y, x] := 0 else img2[x, y] := 0 end if; err := err - deltay; if err < 0 then y := y + ystep; err := err + deltax end if; end do; return img2; end proc:
Mathematica /Wolfram Language
Rasterize[Style[Graphics[Line[{{0,0},{20,10}}]],Antialiasing->False]]
MATLAB
Note: Store this function in a file named "bresenhamLine.m" in the @Bitmap folder for the Bitmap class defined here.

%screen = Bitmap object%startPoint = [x0,y0]%endPoint = [x1,y1] %color = [red,green,blue]functionbresenhamLine(screen,startPoint,endPoint,color)if(any(color>255))error'RGB colors must be between 0 and 255';end%Check for vertical line, x0 == x1if(startPoint(1)==endPoint(1))%Draw vertical linefori=(startPoint(2):endPoint(2))setPixel(screen,[startPoint(1)i],color);endend%Simplified Bresenham algorithmdx=abs(endPoint(1)-startPoint(1));dy=abs(endPoint(2)-startPoint(2));if(startPoint(1)<endPoint(1))sx=1;elsesx=-1;endif(startPoint(2)<endPoint(2))sy=1;elsesy=-1;enderr=dx-dy;pixel=startPoint;while(true)screen.setPixel(pixel,color);%setPixel(x0,y0)if(pixel==endPoint)break;ende2=2*err;if(e2>-dy)err=err-dy;pixel(1)=pixel(1)+sx;endif(e2<dx)err=err+dx;pixel(2)=pixel(2)+sy;endendassignin('caller',inputname(1),screen);%saves the changes to the object end
Sample Usage:
>>img=Bitmap(800,600);>>img.bresenhamLine([400550],[200400],[255255255]);>>img.bresenhamLine([400550],[600400],[255255255]);>>img.bresenhamLine([200400],[350150],[255255255]);>>img.bresenhamLine([600400],[450150],[255255255]);>>img.bresenhamLine([350150],[450150],[255255255]);>>img.bresenhamLine([400550],[400150],[255255255]);>>disp(img)
MAXScript
fn plot img coord steep col = ( if steep then ( swap coord[1] coord[2] ) setPixels img coord col ) fn drawLine img start end col = ( local steep = (abs (end.y - start.y)) > (abs (end.x - start.x)) if steep then ( swap start.x start.y swap end.x end.y ) if start.x > end.x then ( swap start.x end.x swap start.y end.y ) local deltaX = end.x - start.x local deltaY = abs (end.y - start.y) local error = deltaX / 2.0 local yStep = -1 local y = start.y if start.y < end.y then ( yStep = 1 ) for x in start.x to end.x do ( plot img [x, y] steep col error -= deltaY if error < 0 then ( y += yStep error += deltaX ) ) img ) myBitmap = bitmap 512 512 color:(color 0 0 0) myBitmap = drawLine myBitmap [0, 511] [511, 0] #((color 255 255 255)) display myBitmap
Metal
For drawing lines between points in an Apple Metal compute shader.
void drawLine(texture2d<float, access::write> targetTexture, uint2 start, uint2 end); void drawLine(texture2d<float, access::write> targetTexture, uint2 start, uint2 end) { int x = int(start.x); int y = int(start.y); int dx = abs(x - int(end.x)); int dy = abs(y - int(end.y)); int sx = start.x < end.x ? 1 : -1; int sy = start.y < end.y ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2; while (true) { targetTexture.write(float4(1.0), uint2(x, y)); if (x == int(end.x) && y == int(end.y)) { break; } int e2 = err; if (e2 > -dx) { err -= dy; x += sx; } if (e2 < dy) { err += dx; y += sy; } } }
MiniScript
This GUI implementation is for use with Mini Micro.
drawLine=function(img,x0,y0,x1,y1,colr)sign=function(a,b)ifa<bthenreturn1return-1endfunctiondx=abs(x1-x0)sx=sign(x0,x1)dy=abs(y1-y0)sy=sign(y0,y1)ifdx>dythenerr=dxelseerr=-dyendiferr=floor(err/2)whiletrueimg.setPixelx0,y0,colrifx0==x1andy0==y1thenbreake2=errife2>-dxthenerr-=dyx0+=sxendifife2<dythenerr+=dxy0+=syendifendwhileendfunctionimg=Image.create(320,320)drawLineimg,0,0,250,300,color.redgfx.cleargfx.drawImageimg,0,0
Nim
importbitmapprocdrawLine*(img:Image;p,q:Point;color:Color)=letdx=abs(q.x-p.x)sx=ifp.x<q.x:1else:-1dy=abs(q.y-p.y)sy=ifp.y<q.y:1else:-1varp=pq=qerr=(ifdx>dy:dxelse:-dy)div2e2=0whiletrue:img[p.x,p.y]=colorifp==q:breake2=errife2>-dx:err-=dyp.x+=sxife2<dy:err+=dxp.y+=sywhenisMainModule:varimg=newImage(16,16)img.fill(White)img.drawLine((0,7),(7,15),Black)img.drawLine((7,15),(15,7),Black)img.drawLine((15,7),(7,0),Black)img.drawLine((7,0),(0,7),Black)img.print()
- Output:
.......H........ ......H.H....... .....H...H...... ....H.....H..... ...H.......HH... ..H..........H.. .H............H. H..............H .H............H. ..H..........H.. ...H........H... ...H.......H.... ....H.....H..... .....H...H...... ......H.H....... .......H........
OCaml
letdraw_line~img~color~p0:(x0,y0)~p1:(x1,y1)=letsteep=abs(y1-y0)>abs(x1-x0)inletplot=ifsteepthen(funxy->put_pixelimgcoloryx)else(funxy->put_pixelimgcolorxy)inletx0,y0,x1,y1=ifsteeptheny0,x0,y1,x1elsex0,y0,x1,y1inletx0,x1,y0,y1=ifx0>x1thenx1,x0,y1,y0elsex0,x1,y0,y1inletdelta_x=x1-x0anddelta_y=abs(y1-y0)inleterror=-delta_x/2andy_step=ify0<y1then1else-1inletrecloopxyerror=plotxy;ifx<=x1thenleterror=error+delta_yinlety,error=iferror>0then(y+y_step),(error-delta_x)elsey,errorinloop(succx)yerrorinloopx0y0error;;
Pascal
Perl
#! /usr/bin/perlusestrict;useImage::Imlib2;submy_draw_line{my($img,$x0,$y0,$x1,$y1)=@_;my$steep=(abs($y1-$y0)>abs($x1-$x0));if($steep){($y0,$x0)=($x0,$y0);($y1,$x1)=($x1,$y1);}if($x0>$x1){($x1,$x0)=($x0,$x1);($y1,$y0)=($y0,$y1);}my$deltax=$x1-$x0;my$deltay=abs($y1-$y0);my$error=$deltax/2;my$ystep;my$y=$y0;my$x;$ystep=($y0<$y1)?1:-1;for($x=$x0;$x<=$x1;$x+=1){if($steep){$img->draw_point($y,$x);}else{$img->draw_point($x,$y);}$error-=$deltay;if($error<0){$y+=$ystep;$error+=$deltax;}}}# testmy$img=Image::Imlib2->new(160,160);$img->set_color(255,255,255,255);# white$img->fill_rectangle(0,0,160,160);$img->set_color(0,0,0,255);# blackmy_draw_line($img,10,80,80,160);my_draw_line($img,80,160,160,80);my_draw_line($img,160,80,80,10);my_draw_line($img,80,10,10,80);$img->save("test0.png");# let's try the same using its internal algo$img->set_color(255,255,255,255);# white$img->fill_rectangle(0,0,160,160);$img->set_color(0,0,0,255);# black$img->draw_line(10,80,80,160);$img->draw_line(80,160,160,80);$img->draw_line(160,80,80,10);$img->draw_line(80,10,10,80);$img->save("test1.png");exit0;
Images test0.png and test1.png look different since Imlib2 draw lines with antialiasing.
Phix
Modified copy of Euphoria, with a bigger bitmap and a simpler pattern. Requires new_image() from Bitmap, write_ppm() from Write_a_PPM_file.
Note that demo\rosetta\Bresenham_line.exw is just the last 6 lines below preceded by include ppm.e since that contains bresLine() which is also used by several other examples, and covers the above requirements, as shown commented out. Results may be verified with demo\rosetta\viewppm.exw
-- demo\rosetta\Bresenham_line.exw (runnable version)globalfunctionbresLine(sequenceimage,integerx0,y0,x1,y1,colour)-- The line algorithmintegerdimx=length(image),dimy=length(image[1]),deltaX=abs(x1-x0),deltaY=abs(y1-y0),stepX=iff(x0<x1,1,-1),stepY=iff(y0<y1,1,-1),lineError=iff(deltaX>deltaY,deltaX,-deltaY),prevle lineError=round(lineError/2,1)whiletruedoifx0>=1andx0<=dimx andy0>=1andy0<=dimythenimage[x0][y0]=colour endififx0=x1andy0=y1thenexitendifprevle=lineError ifprevle>-deltaXthenlineError-=deltaY x0+=stepX endififprevle<deltaYthenlineError+=deltaX y0+=stepY endifendwhilereturnimage endfunction--include ppm.e -- red, green, blue, white, new_image(), write_ppm(), bresLine() (as distributed, instead of the above)sequencescreenData=new_image(400,300,black) screenData=bresLine(screenData,100,1,50,300,red) screenData=bresLine(screenData,1,180,400,240,green) screenData=bresLine(screenData,200,1,400,150,white) screenData=bresLine(screenData,195,1,205,300,blue) write_ppm("bresenham.ppm",screenData)
PicoLisp
(de brez (Img X Y DX DY) (let SX (cond ((=0 DX) 0) ((gt0 DX) 1) (T (setq DX (- DX)) -1) ) (let SY (cond ((=0 DY) 0) ((gt0 DY) 1) (T (setq DY (- DY)) -1) ) (if (>= DX DY) (let E (- (* 2 DY) DX) (do DX (set (nth Img Y X) 1) (when (ge0 E) (inc 'Y SY) (dec 'E (* 2 DX)) ) (inc 'X SX) (inc 'E (* 2 DY)) ) ) (let E (- (* 2 DX) DY) (do DY (set (nth Img Y X) 1) (when (ge0 E) (inc 'X SX) (dec 'E (* 2 DY)) ) (inc 'Y SY) (inc 'E (* 2 DX)) ) ) ) ) ) ) (let Img (make (do 90 (link (need 120 0)))) # Create image 120 x 90 (brez Img 10 10 100 30) # Draw five lines (brez Img 10 10 100 50) (brez Img 10 10 100 70) (brez Img 10 10 60 70) (brez Img 10 10 20 70) (out "img.pbm" # Write to bitmap file (prinl "P1") (prinl 120 " " 90) (mapc prinl Img) ) )
PL/I
version 1
/* Draw a line from (x0, y0) to (x1, y1). 13 May 2010 */ /* Based on Rosetta code proforma. */ /* Declarations for image and selected color, for 4-bit colors. */ declare image(40,40) bit (4), color bit (4) static initial ('1000'b); draw_line: procedure (xi, yi, xf, yf ); declare (xi, yi, xf, yf) fixed binary (31) nonassignable; declare (x0, y0, x1, y1) fixed binary (31); declare (deltax, deltay, x, y, ystep) fixed binary; declare (error initial (0), delta_error) float; declare steep bit (1); x0 = xi; y = YI; y0 = yi; x1 = xf; y1 = yf; steep = abs(y1 - y0) > abs (x1 - x0); if steep then do; call swap (x0, y0); call swap (x1, y1); end; if x0 > x1 then do; call swap (x0, x1); call swap (y0, y1); end; deltax = x1 - x0; deltay = abs(y1 - y0); delta_error = deltay/deltax; if y0 < y1 then ystep = 1; else ystep = -1; do x = x0 to x1; if steep then image(y, x) = color; else image(x, y) = color; if steep then put skip list (y, x); else put skip list (x, y); error = error + delta_error; if error >= 0.5 then do; y = y + ystep; error = error - 1; end; end; swap: procedure (a, b); declare (a, b) fixed binary (31); declare t fixed binary (31); t = a; a = b; b = t; end swap; end draw_line;
Output from the statement:-
call draw_line(-1, -3, 6, 10);
for a -10:10 x -10:10 grid:
..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.........* ..........|.......**. ..........|.....**... ..........|...**..... ----------+-**------- ..........**......... ........**|.......... .......*..|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|.......... ..........|..........
version 2
*process source xref or(!); brbn:Proc Options(main); /********************************************************************* * 21.05.2014 Walter Pachl * Implementing the pseudo code of * http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm * under 'Simplification' (see also REXX version 2) *********************************************************************/ grid.= dcl image(-2:7,-4:11) char(1); image='.'; image(*,0)='-'; image(0,*)='|'; image(0,0)='+'; call draw_line(-1,-3,6,10); Dcl (i,j) Bin Fixed(31); Do j=11 To -4 By -1; Put Edit(j,' ')(Skip,f(2),a); Do i=-2 To 7; Put Edit(image(i,j))(a); End; End; Put Edit(' 2101234567')(Skip,a); draw_line: procedure (x0,y0,x1,y1); dcl (x0,y0,x1,y1) fixed binary(31); dcl (dx,dy,sx,sy,err,e2) fixed binary(31); dx = abs(x1-x0); dy = abs(y1-y0); if x0 < x1 then sx = 1; else sx = -1; if y0 < y1 then sy = 1; else sy = -1; err = dx-dy; Do Until(x0=x1&y0=y1); image(x0,y0)='X'; e2=err*2; if e2>-dy then do; err=err-dy; x0=x0+sx; End; if e2<dx then do; err=err+dx; y0=y0+sy; End; End; image(x0,y0)='X'; end; end;
output
11 ..|....... 10 ..|.....X. 9 ..|....X.. 8 ..|....X.. 7 ..|...X... 6 ..|...X... 5 ..|..X.... 4 ..|..X.... 3 ..|.X..... 2 ..|.X..... 1 ..|X...... 0 --+X------ -1 ..X....... -2 ..X....... -3 .X|....... -4 ..|....... 2101234567
Prolog
:-use_module(bitmap).:-use_module(bitmapIO).:-use_module(library(clpfd)).% ends when X1 = X2 and Y1 = Y2draw_recursive_line(NPict,Pict,Color,X,X,_DX,_DY,Y,Y,_E,_Sx,_Sy):-set_pixel0(NPict,Pict,[X,Y],Color).draw_recursive_line(NPict,Pict,Color,X,X2,DX,DY,Y,Y2,E,Sx,Sy):-set_pixel0(TPict,Pict,[X,Y],Color),E2#=2*E,% because we can't accumulate error we set Ey or Ex to 1 or 0% depending on whether we need to add dY or dX to the error term(E2>=DY->Ey=1,NX#=X+Sx;Ey=0,NX=X),(E2=<DX->Ex=1,NY#=Y+Sy;Ex=0,NY=Y),NE#=E+DX*Ex+DY*Ey,draw_recursive_line(NPict,TPict,Color,NX,X2,DX,DY,NY,Y2,NE,Sx,Sy).draw_line(NPict,Pict,Color,X1,Y1,X2,Y2):-DeltaY#=Y2-Y1,DeltaX#=X2-X1,(DeltaY<0->Sy=-1;Sy=1),(DeltaX<0->Sx=-1;Sx=1),DX#=abs(DeltaX),DY#=-1*abs(DeltaY),E#=DY+DX,draw_recursive_line(NPict,Pict,Color,X1,X2,DX,DY,Y1,Y2,E,Sx,Sy).init:-new_bitmap(B,[100,100],[255,255,255]),draw_line(NB,B,[0,0,0],2,2,10,90),write_ppm_p6('line.ppm',NB).
PureBasic
ProcedureBresenhamLine(x0,y0,x1,y1)IfAbs(y1-y0)>Abs(x1-x0);steep=#TrueSwapx0,y0Swapx1,y1EndIfIfx0>x1Swapx0,x1Swapy0,y1EndIfdeltax=x1-x0deltay=Abs(y1-y0)error=deltax/2y=y0Ify0<y1ystep=1Elseystep=-1EndIfForx=x0Tox1IfsteepPlot(y,x)ElsePlot(x,y)EndIferror-deltayIferror<0y+ysteperror+deltaxEndIfNextEndProcedure#Window1=0#Image1=0#ImgGadget=0#width=300#height=300Define.iEventDefine.fAngleIfOpenWindow(#Window1,0,0,#width,#height,"Bresenham's Line PureBasic Example",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)IfCreateImage(#Image1,#width,#height)ImageGadget(#ImgGadget,0,0,#width,#height,ImageID(#Image1))StartDrawing(ImageOutput(#Image1))FillArea(0,0,-1,$FFFFFF):FrontColor(0)WhileAngle<2*#PIBresenhamLine(150,150,150+Cos(Angle)*120,150+Sin(Angle)*120)Angle+#PI/60WendStopDrawing()SetGadgetState(#ImgGadget,ImageID(#Image1))RepeatEvent=WaitWindowEvent()UntilEvent=#PB_Event_CloseWindowEndIfEndIf
Python
Extending the example given here and using the algorithm from the Ada solution:
defline(self,x0,y0,x1,y1):"Bresenham's line algorithm"dx=abs(x1-x0)dy=abs(y1-y0)x,y=x0,y0sx=-1ifx0>x1else1sy=-1ify0>y1else1ifdx>dy:err=dx/2.0whilex!=x1:self.set(x,y)err-=dyiferr<0:y+=syerr+=dxx+=sxelse:err=dy/2.0whiley!=y1:self.set(x,y)err-=dxiferr<0:x+=sxerr+=dyy+=syself.set(x,y)Bitmap.line=linebitmap=Bitmap(17,17)forpointsin((1,8,8,16),(8,16,16,8),(16,8,8,1),(8,1,1,8)):bitmap.line(*points)bitmap.chardisplay()'''The origin, 0,0; is the lower left, with x increasing to the right,and Y increasing upwards.The chardisplay above produces the following output :+-----------------+| @ || @ @ || @ @ || @ @ || @ @ || @ @ || @ @ || @ @ || @ @|| @ @ || @ @ || @ @@ || @ @ || @ @ || @ @ || @ || |+-----------------+'''
Not relying on floats
Extending the example given here.
fromfractionsimportFractiondefline(self,x0,y0,x1,y1):rev=reversedifabs(y1-y0)<=abs(x1-x0):x0,y0,x1,y1=y0,x0,y1,x1rev=lambdax:xifx1<x0:x0,y0,x1,y1=x1,y1,x0,y0leny=abs(y1-y0)foriinrange(leny+1):self.set(*rev((round(Fraction(i,leny)*(x1-x0))+x0,(1ify1>y0else-1)*i+y0)))Bitmap.line=line# see test code above
Racket
Port of the Python version.
#lang racket(requireracket/draw)(define(draw-linedcx0y0x1y1)(definedx(abs(-x1x0)))(definedy(abs(-y1y0)))(definesx(if(>x0x1)-11))(definesy(if(>y0y1)-11))(cond[(>dxdy)(letloop([xx0][yy0][err(/dx2.0)])(unless(=xx1)(senddcdraw-pointxy)(definenewerr(-errdy))(if(<newerr0)(loop(+xsx)(+ysy)(+newerrdx))(loop(+xsx)ynewerr))))][else(letloop([xx0][yy0][err(/dy2.0)])(unless(=yy1)(senddcdraw-pointxy)(definenewerr(-errdy))(if(<newerr0)(loop(+xsx)(+ysy)newerr)(loopx(+ysy)(+newerrdy)))))]))(definebm(make-objectbitmap%1717))(definedc(newbitmap-dc%[bitmapbm]))(senddcset-smoothing'unsmoothed)(senddcset-pen"red"1'solid)(for([points'((18816)(816168)(16881)(8118))])(applydraw-line(consdcpoints)))bm
Raku
(formerly Perl 6)
Bitmap class from Bitmap task.
classPixel { hasUInt ($.R, $.G, $.B) } classBitmap { hasUInt ($.width, $.height); hasPixel@!data; methodfill(Pixel$p) { @!data = $p.clonexx ($!width*$!height) } methodpixel( $iwhere ^$!width, $jwhere ^$!height --> Pixel ) isrw { @!data[$i + $j * $!width] } methodset-pixel ($i, $j, Pixel$p) { self.pixel($i, $j) = $p.clone; } methodget-pixel ($i, $j) returnsPixel { self.pixel($i, $j); } } subline(Bitmap$bitmap, $x0iscopy, $x1iscopy, $y0iscopy, $y1iscopy) { my$steep = abs($y1 - $y0) > abs($x1 - $x0); if$steep { ($x0, $y0) = ($y0, $x0); ($x1, $y1) = ($y1, $x1); } if$x0 > $x1 { ($x0, $x1) = ($x1, $x0); ($y0, $y1) = ($y1, $y0); } my$Δx = $x1 - $x0; my$Δy = abs($y1 - $y0); my$error = 0; my$Δerror = $Δy / $Δx; my$y-step = $y0 < $y1 ?? 1 !! -1; my$y = $y0; for$x0 .. $x1 -> $x { my$pix = Pixel.new(R => 100, G => 200, B => 0); if$steep { $bitmap.set-pixel($y, $x, $pix); } else { $bitmap.set-pixel($x, $y, $pix); } $error += $Δerror; if$error >= 0.5 { $y += $y-step; $error -= 1.0; } } }
RapidQ
Use this routine together with the code from Basic bitmap storage to create a full application.
SUB draw_line(x1, y1, x2, y2, colour) x_dist = abs(x2-x1) y_dist = abs(y2-y1) IF y2-y1 < -x_dist OR x2-x1 <= -y_dist THEN SWAP x1, x2 ' Swap start and end points SWAP y1, y2 END IF IF x1 < x2 THEN x_step = 1 ELSE x_step = -1 IF y1 < y2 THEN y_step = 1 ELSE y_step = -1 IF y_dist > x_dist THEN ' steep angle, step by y error = y_dist/2 x = x1 FOR y = y1 TO y2 canvas.Pset(x, y, colour) error = error - x_dist IF error < 0 THEN x = x + x_step error = error + y_dist END IF NEXT y ELSE ' not steep, step by x error = x_dist/2 y = y1 FOR x = x1 TO x2 canvas.Pset(x, y, colour) error = error - y_dist IF error < 0 THEN y = y + y_step error = error + x_dist END IF NEXT y END IF END SUB
Example usage:
SUB PaintCanvas draw_line 200, 10, 100, 200, &H00ff00 draw_line 100, 200, 200, 400, &H00ff00 draw_line 200, 400, 300, 200, &H00ff00 draw_line 300, 200, 200, 10, &H00ff00 END SUB
REXX
version 1
This REXX version has automatic scaling (for displaying the plot), includes a border, accepts lines segments from the
command line, displays a (background) plot field, uses an infinite field, and it also handles multiple line segments.
/*REXX program plots/draws line segments using the Bresenham's line (2D) algorithm. */parseargdata/*obtain optional arguments from the CL*/ifdata=''thendata="(1,8) (8,16) (16,8) (8,1) (1,8)"/* ◄──── a rhombus.*/ data=translate(data,,'()[]{}/,:;')/*elide chaff from the data points. */@.='·'/*use mid─dots chars (plot background).*/dopoints=1whiledata\=''/*put the data points into an array (!)*/parsevardataxydata;!.points=xy/*extract the line segments. */ifpoints==1thendo;minX=x;maxX=x;minY=y;maxY=y/*1st case.*/endminX=min(minX,x);maxX=max(maxX,x);minY=min(minY,y);maxY=max(maxY,y)end/*points*//* [↑] data points pairs in array !. */ border=2/*border: is extra space around plot. */ minX=minX-border*2;maxX=maxX+border*2/*min and max X for the plot display.*/ minY=minY-border;maxY=maxY+border/* " " " Y " " " " */dox=minXtomaxX;@.x.0='─';end/*draw a dash from left ───► right.*/doy=minYtomaxY;@.0.y='│';end/*draw a pipe from lowest ───► highest*/@.0.0='┼'/*define the plot's origin axis point. */doseg=2topoints-1;_=seg-1/*obtain the X and Y line coördinates*/calldrawLine!._,!.seg/*draw (plot) a line segment. */end/*seg*//* [↑] drawing the line segments. *//* [↓] display the plot to terminal. */doy=maxYtominYby-1;_=/*display the plot one line at a time. */dox=minXtomaxX;_=_||@.x.y/*construct/build a line of the plot. */end/*x*//* (a line is a "row" of points.) */say_/*display a line of the plot──►terminal*/end/*y*//* [↑] all done plotting the points. */exit/*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/drawLine:procedureexpose@.;parseargxy,xfyf;parsevalue'-1 -1'withsxsy dx=abs(xf-x);ifx<xfthensx=1/*obtain X range, determine the slope*/dy=abs(yf-y);ify<yfthensy=1/* " Y " " " " */err=dx-dy/*calculate error between adjustments. *//*Θ is the plot character for points. */doforever;@.x.y='Θ'/*plot the points until it's complete. */ifx=xf&y=yfthenreturn/*are the plot points at the finish? */err2=err+err/*calculate double the error value. */iferr2>-dythendo;err=err-dy;x=x+sx;endiferr2<dxthendo;err=err+dx;y=y+sy;endend/*forever*/
- output when using the default input:
···│···················· ···│···················· ···│·······Θ············ ···│······Θ·Θ··········· ···│·····Θ···Θ·········· ···│····Θ·····Θ········· ···│···Θ·······Θ········ ···│···Θ········Θ······· ···│··Θ··········Θ······ ···│·Θ············Θ····· ···│Θ··············Θ···· ···│·Θ············Θ····· ···│··Θ··········Θ······ ···│···Θ·······ΘΘ······· ···│····Θ·····Θ········· ···│·····Θ···Θ·········· ···│······Θ·Θ··········· ···│·······Θ············ ───┼──────────────────── ···│····················
version 2
/* REXX **************************************************************** 21.05.2014 Walter Pachl* Implementing the pseudo code of* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm* under 'Simplification'**********************************************************************/ grid.='.'Doi=-2To7;grid.i.0='-';EndDoj=-4To11;grid.0.j='|';End grid.0.0='+'Callline-1,-3,6,10Doj=11To-4By-1ol=format(j,2)' 'Doi=-2To7ol=ol||grid.i.j EndSayol EndSay' 2101234567'Exitline:ProcedureExposegrid.ParseArgx0,y0,x1,y1 dx=abs(x1-x0) dy=abs(y1-y0)ifx0<x1thensx=1elsesx=-1ify0<y1thensy=1elsesy=-1 err=dx-dy DoForevergrid.x0.y0='X'ifx0=x1&y0=y1ThenLeavee2=2*err ife2>-dythendoerr=err-dy x0=x0+sx endife2<dxthendoerr=err+dx y0=y0+sy endendReturn
output
11 ..|....... 10 ..|.....X. 9 ..|....X.. 8 ..|....X.. 7 ..|...X... 6 ..|...X... 5 ..|..X.... 4 ..|..X.... 3 ..|.X..... 2 ..|.X..... 1 ..|X...... 0 --+X------ -1 ..X....... -2 ..X....... -3 .X|....... -4 ..|....... 2101234567
Ring
load "guilib.ring" load "stdlib.ring" new qapp { win1 = new qwidget() { setwindowtitle("drawing using qpainter") setwinicon(self,"c:\ring\bin\image\browser.png") setgeometry(100,100,500,600) label1 = new qlabel(win1) { setgeometry(10,10,400,400) settext("") } new qpushbutton(win1) { setgeometry(200,400,100,30) settext("draw") setclickevent("draw()") } show() } exec() } func draw p1 = new qpicture() color = new qcolor() { setrgb(0,0,255,255) } pen = new qpen() { setcolor(color) setwidth(1) } new qpainter() { begin(p1) setpen(pen) line = [[50,100,100,190], [100,190,150,100], [150,100,100,10], [100,10,50,100]] for n = 1 to 4 x1=line[n][1] y1=line[n][2] x2=line[n][3] y2=line[n][4] dx = fabs(x2 - x1) sx = sign(x2 - x1) dy = fabs(y2 - y1) sy = sign(y2 - y1) if dx < dy e = dx / 2 else e = dy / 2 ok while true drawline (x1*2,y1*2,x2*2,y2*2) if x1 = x2 if y1 = y2 exit ok ok if dx > dy x1 += sx e -= dy if e < 0 e += dx y1 += sy ok else y1 += sy e -= dx if e < 0 e += dy x1 += sx ok ok end next endpaint() } label1 { setpicture(p1) show() }
Output : Bitmap/Bresenham's algorithm
Ruby
Pixel=Struct.new(:x,:y)classPixmapdefdraw_line(p1,p2,colour)validate_pixel(p1.x,p2.y)validate_pixel(p2.x,p2.y)x1,y1=p1.x,p1.yx2,y2=p2.x,p2.ysteep=(y2-y1).abs>(x2-x1).absifsteepx1,y1=y1,x1x2,y2=y2,x2endifx1>x2x1,x2=x2,x1y1,y2=y2,y1enddeltax=x2-x1deltay=(y2-y1).abserror=deltax/2ystep=y1<y2?1:-1y=y1x1.upto(x2)do|x|pixel=steep?[y,x]:[x,y]self[*pixel]=colourerror-=deltayiferror<0y+=ysteperror+=deltaxendendendendbitmap=Pixmap.new(500,500)bitmap.fill(RGBColour::BLUE)10.step(430,60)do|a|bitmap.draw_line(Pixel[10,10],Pixel[490,a],RGBColour::YELLOW)bitmap.draw_line(Pixel[10,10],Pixel[a,490],RGBColour::YELLOW)endbitmap.draw_line(Pixel[10,10],Pixel[490,490],RGBColour::YELLOW)
Rust
structPoint{x: i32,y: i32}fnmain(){letmutpoints: Vec<Point>=Vec::new();points.append(&mutget_coordinates(1,20,20,28));points.append(&mutget_coordinates(20,28,69,0));draw_line(points,70,30);}fnget_coordinates(x1: i32,y1: i32,x2: i32,y2: i32)-> Vec<Point>{letmutcoordinates: Vec<Point>=vec![];letdx:i32=i32::abs(x2-x1);letdy:i32=i32::abs(y2-y1);letsx:i32={ifx1<x2{1}else{-1}};letsy:i32={ify1<y2{1}else{-1}};letmuterror:i32=(ifdx>dy{dx}else{-dy})/2;letmutcurrent_x:i32=x1;letmutcurrent_y:i32=y1;loop{coordinates.push(Point{x: current_x,y: current_y});ifcurrent_x==x2&¤t_y==y2{break;}leterror2:i32=error;iferror2>-dx{error-=dy;current_x+=sx;}iferror2<dy{error+=dx;current_y+=sy;}}coordinates}fndraw_line(line: std::vec::Vec<Point>,width: i32,height: i32){forcolin0..height{forrowin0..width{letis_point_in_line=line.iter().any(|point|point.x==row&&point.y==col);matchis_point_in_line{true=>print!("@"),_=>print!(".")};}print!("\n");}}
Output:
.....................................................................@ ...................................................................@@. .................................................................@@... ...............................................................@@..... ..............................................................@....... ............................................................@@........ ..........................................................@@.......... ........................................................@@............ .......................................................@.............. .....................................................@@............... ...................................................@@................. .................................................@@................... ................................................@..................... ..............................................@@...................... ............................................@@........................ ..........................................@@.......................... .........................................@............................ .......................................@@............................. .....................................@@............................... ...................................@@................................. .@@...............................@................................... ...@@...........................@@.................................... .....@@.......................@@...................................... .......@@@..................@@........................................ ..........@@...............@.......................................... ............@@@..........@@........................................... ...............@@......@@............................................. .................@@..@@............................................... ...................@@................................................. ......................................................................
Scala
Uses the Scala Basic Bitmap Storage class.
objectBitmapOps{defbresenham(bm:RgbBitmap,x0:Int,y0:Int,x1:Int,y1:Int,c:Color)={valdx=math.abs(x1-x0)valsx=if(x0<x1)1else-1valdy=math.abs(y1-y0)valsy=if(y0<y1)1else-1defit=newIterator[Tuple2[Int,Int]]{varx=x0;vary=y0varerr=(if(dx>dy)dxelse-dy)/2defnext={valres=(x,y)vale2=err;if(e2>-dx){err-=dy;x+=sx}if(e2<dy){err+=dx;y+=sy}res;}defhasNext=(sx*x<=sx*x1&&sy*y<=sy*y1)}for((x,y)<-it)bm.setPixel(x,y,c)}}
Sidef
funcmy_draw_line(img,x0,y0,x1,y1){varsteep=(abs(y1-y0)>abs(x1-x0))if(steep){(y0,x0)=(x0,y0)(y1,x1)=(x1,y1)}if(x0>x1){(x1,x0)=(x0,x1)(y1,y0)=(y0,y1)}vardeltax=(x1-x0)vardeltay=abs(y1-y0)varerror=(deltax/2)vary=y0varystep=(y0<y1?1:-1)x0.to(x1).each{|x|img.draw_point(steep?((y,x)):((x,y)))error-=deltayif(error<0){y+=ysteperror+=deltax}}}require('Image::Imlib2')varimg=%s'Image::Imlib2'.new(160,160)img.set_color(255,255,255,255)# whiteimg.fill_rectangle(0,0,160,160)img.set_color(0,0,0,255)# blackmy_draw_line(img,10,80,80,160)my_draw_line(img,80,160,160,80)my_draw_line(img,160,80,80,10)my_draw_line(img,80,10,10,80)img.save("test0.png");# let's try the same using its internal algoimg.set_color(255,255,255,255)# whiteimg.fill_rectangle(0,0,160,160)img.set_color(0,0,0,255)# blackimg.draw_line(10,80,80,160)img.draw_line(80,160,160,80)img.draw_line(160,80,80,10)img.draw_line(80,10,10,80)img.save("test1.png")
SparForte
As a structured script.
#!/usr/local/bin/sparpragmaannotate(summary,"DrawLine")@(description,"Draw a line given 2 points with the Bresenham's algorithm.")@(see_also,"http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm")@(author,"Ken O. Burtch");pragmalicense(unrestricted);pragmarestriction(no_external_commands);proceduredrawlineis-- Spar 1.x has only single-dimensional arrays but we can simulate a-- two dimensional array that has been folded into a 1D arraywidth:constantpositive:=20;height:constantpositive:=20;typeimage_arrayisarray(1..400)ofcharacter;Picture:image_array;-- Line-- Draw a line between two coordinates using the given characterprocedureLine(Start_X: positive;Start_Y: positive;Stop_X: positive;Stop_Y: positive;Color: character)is-- at this point, formal parameters are defined but the actual values aren't defined!-- but creating a dummy Line in a test script works?DX:constantfloat:=abs(float(Stop_X)-float(Start_X));DY:constantfloat:=abs(float(Stop_Y)-float(Start_Y));Err:float;X:positive:=Start_X;Y:positive:=Start_Y;Step_X:integer:=1;Step_Y:integer:=1;beginifStart_X>Stop_XthenStep_X:=-1;endif;ifStart_Y>Stop_YthenStep_Y:=-1;endif;ifDX>DYthenErr:=DX/2.0;whileX/=Stop_XloopPicture(X+width*(Y-1)):=Color;Err:=@-DY;ifErr<0.0thenY:=positive(integer(@)+Step_Y);Err:=@+DX;endif;X:=positive(integer(@)+Step_X);endloop;elseErr:=DY/2.0;whileY/=Stop_YloopPicture(X+height*(Y-1)):=Color;Err:=@-DX;ifErr<0.0thenX:=positive(integer(@)+Step_X);Err:=@+DY;endif;Y:=positive(integer(@)+Step_Y);endloop;endif;Picture(X+width*(Y-1)):=Color;endLine;-- new_picture-- Erase the picture by filling it with spaces.procedurenew_pictureisbeginforiinarrays.first(Picture)..arrays.last(Picture)loopPicture(i):=' ';endloop;endnew_picture;-- render-- Draw the contents of the picture area.procedurerenderisbeginforiinarrays.first(Picture)..arrays.last(Picture)loopput(Picture(i));ifimodwidth=0thennew_line;endif;endloop;endrender;beginnew_picture;Line(1,8,8,16,'X');Line(8,16,16,8,'X');Line(16,8,8,1,'X');Line(8,1,1,8,'X');render;enddrawline;
Tcl
packagerequireTcl8.5packagerequireTk procdrawLine{imagecolourpoint0point1}{lassign$point0x0y0 lassign$point1x1y1 setsteep[expr{abs($y1-$y0)>abs($x1-$x0)}]if{$steep}{lassign[list$x0$y0]y0x0 lassign[list$x1$y1]y1x1 }if{$x0>$x1}{lassign[list$x0$x1]x1x0 lassign[list$y0$y1]y1y0 }setdeltax[expr{$x1-$x0}]setdeltay[expr{abs($y1-$y0)}]seterror[expr{$deltax/2}]setystep[expr{$y0<$y1?1:-1}]for{setx$x0;sety$y0}{$x<=$x1}{incrx}{setPixel$image$colour[expr{$steep?[list$y$x]:[list$x$y]}]increrror-$deltayif{$error<0}{incry$ystepincrerror$deltax}}}# create the image and display itsetimg[newImage200100]label.l-image$imgpack.l fill$imgblack drawLine$imgyellow{2020}{18080}drawLine$imgyellow{18020}{2080}
TI-89 BASIC
(lx0, ly0, lx1, ly1) Prgm Local steep, x, y, dx, dy, ystep, error, tmp abs(ly1 - ly0) > abs(lx1 - lx0) → steep If steep Then lx0 → tmp ly0 → lx0 tmp → ly0 lx1 → tmp ly1 → lx1 tmp → ly1 EndIf If lx0 > lx1 Then lx0 → tmp lx1 → lx0 tmp → lx1 ly0 → tmp ly1 → ly0 tmp → ly1 EndIf lx1 - lx0 → dx abs(ly1 - ly0) → dy when(ly0 < ly1, 1, –1) → ystep intDiv(dx, 2) → error ly0 → y For x,lx0,lx1 If steep Then: PxlChg x, y :Else: PxlChg y, x :EndIf error - dy → error If error < 0 Then y + ystep → y error + dx → error EndIf EndFor EndPrgm
VBScript
'Bitmap/Bresenham's line algorithm - VBScript - 13/05/2019Dimmap(48,40),list(10),ox,oydata=Array(1,8,8,16,16,8,8,1,1,8)Fori=0ToUBound(map,1):Forj=0ToUBound(map,2)map(i,j)="."Next:Next'j, ipoints=(UBound(data)+1)/2Forp=1Topointsx=data((p-1)*2)y=data((p-1)*2+1)list(p)=Array(x,y)Ifp=1ThenminX=x:maxX=x:minY=y:maxY=yIfx<minXThenminX=xIfx>maxXThenmaxX=xIfy<minYThenminY=yIfy>maxYThenmaxY=yNext'pborder=2minX=minX-border*2:maxX=maxX+border*2minY=minY-border:maxY=maxY+borderox=-minX:oy=-minYwx=UBound(map,1)-ox:IfmaxX>wxThenmaxX=wxwy=UBound(map,2)-oy:IfmaxY>wyThenmaxY=wyForx=minXTomaxX:map(x+ox,0+oy)="-":Next'xFory=minYTomaxY:map(0+ox,y+oy)="|":Next'ymap(ox,oy)="+"Forp=1Topoints-1draw_linelist(p),list(p+1)Next'pFory=maxYTominYStep-1line=""Forx=minXTomaxXline=line&map(x+ox,y+oy)Next'xWscript.EcholineNext'ySubdraw_line(p1,p2)Dimx,y,xf,yf,dx,dy,sx,sy,err,err2x=p1(0):y=p1(1)xf=p2(0):yf=p2(1)dx=Abs(xf-x):dy=Abs(yf-y)Ifx<xfThensx=+1:Elsesx=-1Ify<yfThensy=+1:Elsesy=-1err=dx-dyDomap(x+ox,y+oy)="X"Ifx=xfAndy=yfThenExitDoerr2=err+errIferr2>-dyThenerr=err-dy:x=x+sxIferr2<dxThenerr=err+dx:y=y+syLoopEndSub'draw_line
- Output:
...|.................... ...|.................... ...|.......X............ ...|......X.X........... ...|.....X...X.......... ...|....X.....X......... ...|...X.......X........ ...|...X........X....... ...|..X..........X...... ...|.X............X..... ...|X..............X.... ...|.X............X..... ...|..X..........X...... ...|...X.......XX....... ...|....X.....X......... ...|.....X...X.......... ...|......X.X........... ...|.......X............ ---+-------------------- ...|....................
Vedit macro language
// Daw a line using Bresenham's line algorithm. // #1=x1, #2=y1; #3=x2, #4=y2 :DRAW_LINE: Num_Push(31,35) #31 = abs(#3-#1) // x distance #32 = abs(#4-#2) // y distance if (#4-#2 < -#31 || #3-#1 <= -#32) { #99=#1; #1=#3; #3=#99 // swap start and end points #99=#2; #2=#4; #4=#99 } if (#1 < #3) { #34=1 } else { #34=-1 } // x step if (#2 < #4) { #35=1 } else { #35=-1 } // y step if (#32 > #31) { // steep angle, step by Y #33 = #32 / 2 // error distance while (#2 <= #4) { Call("DRAW_PIXEL") #33 -= #31 if (#33 < 0) { #1 += #34 // move right #33 += #32 } #2++ // move up } } else { // not steep, step by X #33 = #31 / 2 while (#1 <= #3) { Call("DRAW_PIXEL") #33 -= #32 if (#33 < 0) { #2 += #35 // move up #33 += #31 } #1++ // move right } } Num_Pop(31,35) return
Wart
# doesn't handle vertical lines def (line x0 y0 x1 y1) let steep ((> abs) y1-y0 x1-x0) when steep swap! x0 y0 swap! x1 y1 when (x0 > x1) swap! x0 x1 swap! y0 y1 withs (deltax x1-x0 deltay (abs y1-y0) error deltax/2 ystep (if (y0 < y1) 1 -1) y y0) for x x0 (x <= x1) ++x if steep plot y x plot x y error -= deltay when (error < 0) y += ystep error += deltax
Wren
Requires version 1.3.0 of DOME or later.
import"graphics"forCanvas,ImageData,Colorimport"dome"forWindowclassGame{staticbmpCreate(name,w,h){ImageData.create(name,w,h)}staticbmpFill(name,col){varimage=ImageData[name]for(xin0...image.width){for(yin0...image.height)image.pset(x,y,col)}}staticbmpPset(name,x,y,col){ImageData[name].pset(x,y,col)}staticbmpPget(name,x,y){ImageData[name].pget(x,y)}staticbmpLine(name,x0,y0,x1,y1,col){vardx=(x1-x0).absvardy=(y1-y0).absvarsx=(x0<x1)?1:-1varsy=(y0<y1)?1:-1varerr=((dx>dy?dx:-dy)/2).floorwhile(true){bmpPset(name,x0,y0,col)if(x0==x1&&y0==y1)breakvare2=errif(e2>-dx){err=err-dyx0=x0+sx}if(e2<dy){err=err+dxy0=y0+sy}}}staticinit(){Window.title="Bresenham's line algorithm"varsize=200Window.resize(size,size)Canvas.resize(size,size)varname="bresenham"varbmp=bmpCreate(name,size,size)bmpFill(name,Color.white)bmpLine(name,50,100,100,190,Color.black)bmpLine(name,100,190,150,100,Color.black)bmpLine(name,150,100,100,10,Color.black)bmpLine(name,100,10,50,100,Color.black)bmp.draw(0,0)}staticupdate(){}staticdraw(alpha){}}
XPL0
Bresenham line draw is built-in.
include c:\cxpl\codes; \intrinsic 'code' declarations [SetVid($112); \set 640x480 graphics in 24-bit color Move(10, 20); \set start of line segment Line(600, 400, $123456);\draw line segment, red=$12, green=$34, blue=$56 if ChIn(1) then []; \wait for keystroke while viewing graphic screen SetVid(3); \restore normal text mode ]
zkl

Algorithm from Wikipedia plus other functions so I can reference this code in other examples.
ppm:=PPM(200,200,0xFF|FF|FF); ppm.line(50,100, 100,190, 0); ppm.line(100,190, 150,100, 0); ppm.line(150,100, 100,10, 0); ppm.line(100,10, 50,100, 0); ppm.writeJPGFile("line.jpg");
class PPM{ // (0,0) is logically bottom left fcn init(width,height,rgb=0){ sz:=width*height; var [const] data=Data(sz*3).fill(rgb.toBigEndian(3).toData()), // initialize to 24bit Black (RGB=000) w=width, h=height; } fcn fill(rgb){ data.fill(rgb.toBigEndian(3).toData()) } fcn __sGet(x,y) { data.toBigEndian(3*y*w + 3*x,3); } //ppm[x,y] fcn __sSet(rgb,x,y){ data[3*y*w + x*3,3]=rgb.toBigEndian(3); rgb } //ppm[x,y]=rgb fcn write(out,raw=False){ // write bottom to top to move (0,0) from top left to bottom left out.write("P6\n#rosettacode PPM\n%d %d\n255\n".fmt(w,h)); if(raw) out.write(data); else [h-1..0, -1].pump(out,'wrap(h){ data.seek(3*h*w); data.read(3*w) }); } fcn writeJPGFile(fname){ // Linux, using imagemagick System.popen(0'|convert ppm:- jpg:"%s"|.fmt(fname),"w") : write(_,vm.pasteArgs(1)); } fcn readJPGFile(fileName){ // Linux, using imagemagick p:=System.popen("convert \"%s\" ppm:-".fmt(fileName),"r"); img:=PPM.readPPM(p); p.close(); img } fcn readPPMFile(fileName){ f:=File(fileName,"rb"); ppm:=readPPM(f); f.close(); ppm } fcn readPPM(image){ // image is a PPM byte stream // header is "P6\n[#comment\n]<w> <h>\nmaxPixelValue\n image.readln(); // "P6" while("#"==(text:=image.readln().strip())[0]){} w,h:=text.split().apply("toInt"); image.readln(); // max pixel value ppm,sz,buffer:=PPM(w,h), 3*w, Data(sz); ppm.data.clear(); // gonna write file image data // image is stored upside down in my data structure do(h){ ppm.data.insert(0, image.read(sz,buffer)) } ppm } fcn circle(x0,y0,r,rgb){ x:=r; y:=0; radiusError:=1-x; while(x >= y){ __sSet(rgb, x + x0, y + y0); __sSet(rgb, y + x0, x + y0); __sSet(rgb,-x + x0, y + y0); __sSet(rgb,-y + x0, x + y0); self[-x + x0, -y + y0]=rgb; // or do it this way, __sSet gets called as above self[-y + x0, -x + y0]=rgb; self[ x + x0, -y + y0]=rgb; self[ y + x0, -x + y0]=rgb; y+=1; if (radiusError<0) radiusError+=2*y + 1; else{ x-=1; radiusError+=2*(y - x + 1); } } } fcn cross(x,y,rgb=0xff|00,len=10){ a:=len/2; b:=len-a; line(x-a,y, x+b,y,rgb); line(x,y-a, x,y+b,rgb); } fcn line(x0,y0, x1,y1, rgb){ dx:=(x1-x0).abs(); dy:=(y1-y0).abs(); if(x0 < x1) sx:=1 else sx:=-1; if(y0 < y1) sy:=1 else sy:=-1; err:=dx - dy; while(1){ __sSet(rgb,x0,y0); if(x0==x1 and y0==y1) break; e2:=2*err; if(e2 > -dy){ err=err - dy; x0=x0 + sx; } if(e2 < dx) { err=err + dx; y0=y0 + sy; } } } fcn flood(x,y, repl){ // slow! targ:=self[x,y]; (stack:=List.createLong(10000)).append(T(x,y)); while(stack){ x,y:=stack.pop(); if((0<=y<h) and (0<=x<w)){ p:=self[x,y]; if(p==targ){ self[x,y]=repl; stack.append( T(x-1,y), T(x+1,y), T(x, y-1), T(x, y+1) ); } } } } }
- Graphics algorithms
- Geometry
- Programming Tasks
- Raster graphics operations
- 11l
- 360 Assembly
- Action!
- Action! Bitmap tools
- Ada
- ALGOL 68
- Applesoft BASIC
- Arturo
- Assembly
- ATS
- AutoHotkey
- AutoIt
- Bash
- BASIC
- Batch File
- BBC BASIC
- C
- C sharp
- C++
- Clojure
- CoffeeScript
- Commodore BASIC
- Common Lisp
- D
- Delphi
- E
- EasyLang
- Elm
- Erlang
- ERRE
- Euphoria
- F Sharp
- Windows Presentation Foundation
- Factor
- FBSL
- Forth
- Fortran
- FreeBASIC
- Go
- Haskell
- J
- Java
- JavaScript
- Julia
- Ksh
- Lua
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- MAXScript
- Metal
- MiniScript
- Nim
- OCaml
- Pascal
- Perl
- Imlib2
- Phix
- PicoLisp
- PL/I
- PL/I examples needing attention
- Examples needing attention
- Prolog
- PureBasic
- Python
- Racket
- Raku
- RapidQ
- REXX
- Ring
- Ruby
- Rust
- Scala
- Sidef
- SparForte
- Tcl
- Tk
- TI-89 BASIC
- VBScript
- Vedit macro language
- Wart
- Wren
- DOME
- XPL0
- Zkl
- AWK/Omit
- PARI/GP/Omit