Bitmap/Bresenham's line algorithm: Difference between revisions

(→‎{{header|Go}}: update for enhanced code in bitmap task, also added demonstration program)
imported>Chinhouse
(203 intermediate revisions by 75 users not shown)
Line 1:
{{task|Raster graphics operations}}[[Category:Graphics algorithms]]
[[Category:Geometry]]
{{task|Raster graphics operations}}
 
;Task:
Using the data storage type defined [[Basic_bitmap_storage|on this page]] for raster graphics images, draw a line given 2 points with the [[wp:Bresenham's_line_algorithm|Bresenham's algorithm]].
Using the data storage type defined on the [[Bitmap]] page for raster graphics images,
<br>draw a line given two points with [[wp:Bresenham's line algorithm|Bresenham's line algorithm]].
<br><br>
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">T Colour
Byte r, g, b
 
F (r, g, b)
.r = r
.g = g
.b = b
 
F ==(other)
R .r == other.r & .g == other.g & .b == other.b
 
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()</syntaxhighlight>
 
{{out}}
<pre>
+-----------------+
| @ |
| @ @ |
| @ @ |
| @ @ |
| @ @ |
| @ @ |
| @ @ |
| @ @ |
| @ @|
| @ @ |
| @ @ |
| @ @@ |
| @ @ |
| @ @ |
| @ @ |
| @ |
| |
+-----------------+
</pre>
=={{header|360 Assembly}}==
{{trans|Rexx}}
<syntaxhighlight lang="360asm">* 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 </syntaxhighlight>
{{out}}
<pre>
...|....................
...|....................
...|.......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............
---+--------------------
...|....................
</pre>
=={{header|Action!}}==
Part of the task is available in [http://www.rosettacode.org/wiki/Category:Action!_Bitmap_tools#RGBLINE.ACT RGBLINE.ACT].
{{libheader|Action! Bitmap tools}}
<syntaxhighlight lang="action!">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</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Bresenham's_line_algorithm.png Screenshot from Atari 8-bit computer]
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">procedure Line (Picture : in out Image; Start, Stop : Point; Color : Pixel) is
DX : constant Float := abs Float (Stop.X - Start.X);
DY : constant Float := abs Float (Stop.Y - Start.Y);
Line 43 ⟶ 441:
end if;
Picture (X, Y) := Color; -- Ensure dots to be drawn
end Line;</langsyntaxhighlight>
The test program's
<langsyntaxhighlight lang="ada"> X : Image (1..16, 1..16);
begin
Fill (X, White);
Line 52 ⟶ 450:
Line (X, (16, 8), ( 8, 1), Black);
Line (X, ( 8, 1), ( 1, 8), Black);
Print (X);</langsyntaxhighlight>
sample output
<pre>
Line 74 ⟶ 472:
=={{header|ALGOL 68}}==
{{trans|Ada}}
{{works with|ALGOL 68|Revision 1 - one minor extension to language used - PRAGMA READ, similar to C's #include directive.}}
 
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.6 algol68g-2.6].}}
{{works with|ALGOL 68|Standard - '''pragmat''' '''read''' is an extension}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
'''File: prelude/Bitmap/Bresenhams_line_algorithm.a68'''<syntaxhighlight lang="algol68"># -*- coding: utf-8 -*- #
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386 - '''pragmat''' '''read''' is not part of algol68rs}} -->
<lang algol68>PRAGMAT READ "Basic_bitmap_storage.a68" PRAGMAT;
 
line OF class image := (REF IMAGE picture, POINT start, stop, PIXEL color)VOID:
Line 119 ⟶ 516:
END # line #;
 
SKIP</syntaxhighlight>'''File: test/Bitmap/Bresenhams_line_algorithm.a68'''<syntaxhighlight lang="algol68">#!/usr/bin/a68g --script #
###
# -*- coding: utf-8 -*- #
The test program:
###
PR READ "prelude/Bitmap.a68" PR; # c.f. [[rc:Bitmap]] #
IF test THEN
PR READ "prelude/Bitmap/Bresenhams_line_algorithm.a68" PR;
 
### The test program: ###
test:(
REF IMAGE x = INIT LOC[1:16, 1:16]PIXEL;
(fill OF class image)(x, white OF class image);
Line 130 ⟶ 531:
(line OF class image)(x, ( 8, 1), ( 1, 8), black OF class image);
(print OF class image)(x)
)</syntaxhighlight>'''Output:'''
FI</lang>
Output:
<pre>
ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff
Line 150 ⟶ 550:
ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffff
</pre>
=={{header|Applesoft BASIC}}==
<syntaxhighlight lang="gwbasic"> 10 HGR :FULLSCREEN = PEEK (49234)
20 HCOLOR= 3
30 FOR N = 3 TO 279 STEP 4
40 X1 = 276:Y1 = 189:X2 = N:Y2 = 1: GOSUB 100"PLOT LINE"
50 NEXT N
60 FOR N = 3 TO 191 STEP 3
70 X1 = 276:Y1 = 190:X2 = 2:Y2 = N: GOSUB 100"PLOT LINE"
80 NEXT N
90 END
100 DX = ABS (X2 - X1)
110 SX = SGN (X2 - X1)
120 DY = - ABS (Y2 - Y1)
130 SY = SGN (Y2 - Y1)
140 ERR = DX + DY
150 FOR WHILE = 0 TO 1 STEP 0
160 HPLOT X1,Y1
170 IF X1 = X2 AND Y1 = Y2 THEN RETURN
180 E2 = 2 * ERR
190 IF E2 > = DY AND X1 = X2 THEN RETURN
200 IF E2 > = DY THEN ERR = ERR + DY:X1 = X1 + SX
210 IF E2 < = DX AND Y1 = Y2 THEN RETURN
220 IF E2 < = DX THEN ERR = ERR + DX:Y1 = Y1 + SY
230 NEXT WHILE</syntaxhighlight>
=={{header|Assembly}}==
16 bit Intel 8086\80486 Assembly for dos, see [http://en.wikipedia.org/wiki/X86_assembly_language x86 assembly language].
To run this code you will need to use Dos emulator.
<pre>
.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
</pre>
=={{header|ATS}}==
See [[Bresenham_tasks_in_ATS]].
 
=={{header|AutoHotkey}}==
 
<syntaxhighlight lang="autohotkey">Blue := Color(0,0,255)
White := Color(255,255,255)
Bitmap := Bitmap(100,100,Blue) ;create a 100*100 blue bitmap
Line(Bitmap,White,5,10,60,80) ;draw a white line from (5,10) to (60,80)
Bitmap.Write("Line.ppm") ;write the bitmap to file
 
Line(ByRef Bitmap,ByRef Color,PosX1,PosY1,PosX2,PosY2)
{
DeltaX := Abs(PosX2 - PosX1), DeltaY := -Abs(PosY2 - PosY1) ;calculate deltas
StepX := ((PosX1 < PosX2) ? 1 : -1), StepY := ((PosY1 < PosY2) ? 1 : -1) ;calculate steps
ErrorValue := DeltaX + DeltaY ;calculate error value
Loop ;loop over the pixel values
{
Bitmap[PosX1,PosX2] := Color
If (PosX1 = PosX2 && PosY1 = PosY2)
Break
Temp1 := ErrorValue << 1, ((Temp1 > DeltaY) ? (ErrorValue += DeltaY, PosX1 += StepX) : ""), ((Temp1 < DeltaX) ? (ErrorValue += DeltaX, PosY1 += StepY) : "") ;move forward
}
}</syntaxhighlight>
 
=={{header|AutoIt}}==
 
<syntaxhighlight lang="autohotkey">Local $var = drawBresenhamLine(2, 3, 2, 6)
 
Func drawBresenhamLine($iX0, $iY0, $iX1, $iY1)
Local $iDx = Abs($iX1 - $iX0)
Local $iSx = $iX0 < $iX1 ? 1 : -1
Local $iDy = Abs($iY1 - $iY0)
Local $iSy = $iY0 < $iY1 ? 1 : -1
Local $iErr = ($iDx > $iDy ? $iDx : -$iDy) / 2, $e2
 
While $iX0 <= $iX1
ConsoleWrite("plot( $x=" & $iX0 & ", $y=" & $iY0 & " )" & @LF)
If ($iX0 = $iX1) And ($iY0 = $iY1) Then Return
$e2 = $iErr
If ($e2 > -$iDx) Then
$iErr -= $iDy
$iX0 += $iSx
EndIf
If ($e2 < $iDy) Then
$iErr += $iDx
$iY0 += $iSy
EndIf
WEnd
EndFunc ;==>drawBresenhamLine</syntaxhighlight>
=={{header|bash}}==
<syntaxhighlight lang="bash">#! /bin/bash
 
function line {
x0=$1
y0=$2
x1=$3
y1=$4
if (( x0 > x1 ))
then
(( dx = x0 - x1 ))
(( sx = -1 ))
else
(( dx = x1 - x0 ))
(( sx = 1 ))
fi
if (( y0 > y1 ))
then
(( dy = y0 - y1 ))
(( sy = -1 ))
else
(( dy = y1 - y0 ))
(( sy = 1 ))
fi
if (( dx > dy ))
then
(( err = dx ))
else
(( err = -dy ))
fi
(( err /= 2 ))
(( e2 = 0 ))
while :
do
echo -en "\e[${y0};${x0}H#\e[K"
(( x0 == x1 && y0 == y1 )) && return
(( e2 = err ))
if (( e2 > -dx ))
then
(( err -= dy ))
(( x0 += sx ))
fi
if (( e2 < dy ))
then
(( err += dx ))
(( y0 += sy ))
fi
done
}
 
# Draw a full screen diamond
COLS=$( tput cols )
LINS=$( tput lines )
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)) 1
echo -e "\e[${LINS}H"</syntaxhighlight>
=={{header|BASIC}}==
<syntaxhighlight lang="qbasic"> 1500 REM === Draw a line. Ported from C version
1510 REM Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
1520 DX = ABS(X2 - X1):SX = -1:IF X1 < X2 THEN SX = 1
1530 DY = ABS(Y2 - Y1):SY = -1:IF Y1 < Y2 THEN SY = 1
1540 ER = -DY:IF DX > DY THEN ER = DX
1550 ER = INT(ER / 2)
1560 PLOT X1,Y1:REM This command may differ depending on BASIC dialect
1570 IF X1 = X2 AND Y1 = Y2 THEN RETURN
1580 E2 = ER
1590 IF E2 > -DX THEN ER = ER - DY:X1 = X1 + SX
1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY
1610 GOTO 1560</syntaxhighlight>
=={{header|Batch File}}==
<syntaxhighlight lang="dos">@echo off
setlocal enabledelayedexpansion
 
set width=87
set height=51
 
mode %width%,%height%
 
set "grid="
set /a resolution=height*width
for /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
 
:line
set x1=%1
set y1=%2
set x2=%3
set y2=%4
 
set /a dx=x2-x1
set /a dy=y2-y1
 
::Clipping done to avoid overflow
 
if %dx% neq 0 set /a o=y1 - ( x1 * dy / dx )
if %x1% leq %x2% (
if %x1% geq %width% goto :eof
if %x2% lss 0 goto :eof
 
if %x1% lss 0 (
if %dx% neq 0 set y1=%o%
set x1=0
)
if %x2% geq %width% (
set /a x2= width - 1
if %dx% neq 0 set /a "y2= x2 * dy / dx + o"
)
) else (
if %x2% geq %width% goto :eof
if %x1% lss 0 goto :eof
 
if %x2% lss 0 (
if %dx% neq 0 set y2=%o%
set x2=0
)
if %x1% geq %width% (
set /a x1=width - 1
if %dx% neq 0 set /a "y1= x1 * dy / dx + o"
)
)
if %y1% leq %y2% (
if %y1% geq %height% goto :eof
if %y2% lss 0 goto :eof
 
if %y1% lss 0 (
set y1=0
if %dx% neq 0 set /a x1= - o * dx /dy
)
if %y2% geq %height% (
set /a y2=height-1
if %dx% neq 0 set /a "x2= (y2 - o) * dx /dy"
)
) else (
if %y2% geq %height% goto :eof
if %y1% lss 0 goto :eof
 
if %y2% lss 0 (
set y2=0
if %dx% neq 0 set /a "x2= - o * dx /dy"
)
if %y1% geq %height% (
set /a y1=height-1
if %dx% neq 0 set /a "x1= (y1 - o) * dx /dy"
)
)
 
:: Start of Bresenham's algorithm
 
set stepy=1
set stepx=1
 
set /a dx=x2-x1
set /a dy=y2-y1
 
if %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 /a cursorP=cursor+1
for /f "tokens=1-2" %%g in ("!cursor! !cursorP!") do set "grid=!grid:~0,%%g!Û!grid:~%%h!"
if !fraction! geq 0 (
set /a y1+=stepy
set /a cursor+=stepy*width
set /a fraction-=dx
)
set /a fraction+=dy
set /a cursor+=stepx
)
) else (
set /a "fraction=dx-(dy>>1)"
set /a "cursor=y1*width + x1"
for /l %%y in (%y1%,%stepy%,%y2%) do (
set /a cursorP=cursor+1
for /f "tokens=1-2" %%g in ("!cursor! !cursorP!") do set "grid=!grid:~0,%%g!Û!grid:~%%h!"
if !fraction! geq 0 (
set /a x1+=stepx
set /a cursor+=stepx
set /a fraction-=dy
)
set /a fraction+=dx
set /a cursor+=width*stepy
)
)
goto :eof</syntaxhighlight>
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> Width% = 200
Height% = 200
REM Set window size:
VDU 23,22,Width%;Height%;8,16,16,128
REM 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)
END
DEF PROCbresenham(x1%,y1%,x2%,y2%,r%,g%,b%)
LOCAL dx%, dy%, sx%, sy%, e
dx% = ABS(x2% - x1%) : sx% = SGN(x2% - x1%)
dy% = ABS(y2% - y1%) : sy% = SGN(y2% - y1%)
IF dx% > dy% e = dx% / 2 ELSE e = dy% / 2
REPEAT
PROCsetpixel(x1%,y1%,r%,g%,b%)
IF x1% = x2% IF y1% = y2% EXIT REPEAT
IF dx% > dy% THEN
x1% += sx% : e -= dy% : IF e < 0 e += dx% : y1% += sy%
ELSE
y1% += sy% : e -= dx% : IF e < 0 e += dy% : x1% += sx%
ENDIF
UNTIL FALSE
ENDPROC
DEF PROCsetpixel(x%,y%,r%,g%,b%)
COLOUR 1,r%,g%,b%
GCOL 1
LINE x%*2,y%*2,x%*2,y%*2
ENDPROC</syntaxhighlight>
[[File:bresenham_bbc.gif]]
=={{header|C}}==
 
Instead of swaps in the initialisation use error calculation for both directions x and y simultaneously:
<langsyntaxhighlight Clang="c">void line(int x0, int y0, int x1, int y1) {
 
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
Line 167 ⟶ 1,082:
if (e2 < dy) { err += dx; y0 += sy; }
}
}</langsyntaxhighlight>
=={{header|C sharp|C#}}==
 
Port of the C version.
<syntaxhighlight lang="csharp">using System;
using System.Drawing;
using System.Drawing.Imaging;
static class Program
{
static void Main()
{
new Bitmap(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);
}
static Bitmap DrawLine(this Bitmap bitmap, int x0, int y0, int x1, int y1, Color color)
{
int dx = Math.Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = Math.Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (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; }
}
return bitmap;
}
}</syntaxhighlight>
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
void Line( const float x1, const float y1, const float x2, const float y2, const Color& color )
{
// Bresenham's line algorithm
const bool steep = (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);
}
 
const float dx = x2 - x1;
const float dy = fabs(y2 - y1);
float error = dx / 2.0f;
const int ystep = (y1 < y2) ? 1 : -1;
int y = (int)y1;
 
const int maxX = (int)x2;
 
for(int x=(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;
}
}
}
</syntaxhighlight>
</lang>
 
=={{header|Clojure}}==
 
<langsyntaxhighlight lang="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."
[buffer x1 y1 x2 y2 pixel]
(let [dist-x (Math/abs (- x1 x2))
dist-y (Math/abs (- y1 y2))
steep (> dist-y dist-x)]
(let [[x1 y1 x2 y2] (if steep [y1 x1 y2 x2] [x1 y1 x2 y2])]
(let [[x1 y1 x2 y2] (if (> x1 x2) [x2 y2 x1 y1] [x1 y1 x2 y2])]
(let [delta-x (- x2 x1)
delta-y (Math/abs (- y1 y2))
y-step (if (< y1 y2) 1 -1)]
 
(let [plot (if steep
#(.setRGB buffer (int %1) (int %2) pixel)
#(.setRGB buffer (int %2) (int %1) pixel))]
(loop [x x1 y y1 error (Math/floor (/ delta-x 2)) ]
(plot x y)
(if (< x x2)
; Rather then rebind error, test that it is less than delta-y rather than zero
(if (< error delta-y)
(recur (inc x) (+ y y-step) (+ error (- delta-x delta-y)))
(recur (inc x) y (- error delta-y)))))))))))
</syntaxhighlight>
</lang>
=={{header|CoffeeScript}}==
 
<syntaxhighlight lang="coffeescript">
drawBresenhamLine = (x0, y0, x1, y1) ->
dx = Math.abs(x1 - x0)
sx = if x0 < x1 then 1 else -1
dy = Math.abs(y1 - y0)
sy = if y0 < y1 then 1 else -1
err = (if dx>dy then dx else -dy) / 2
 
loop
setPixel(x0, y0)
break if x0 == x1 && y0 == y1
e2 = err
if e2 > -dx
err -= dy
x0 += sx
if e2 < dy
err += dx
y0 += sy
null
</syntaxhighlight>
=={{header|Commodore BASIC}}==
<syntaxhighlight lang="basic">
10 rem bresenham line algorihm
20 rem translated from purebasic
30 x0=10 : rem start x co-ord
40 y0=15 : rem start y co-ord
50 x1=30 : rem end x co-ord
60 y1=20 : rem end y co-ord
70 se=0 : rem 0 = steep 1 = !steep
80 ns=25 : rem num segments
90 dim pt(ns,2) : rem points in line
100 sc=1024 : rem start of screen memory
110 sw=40 : rem screen width
120 sh=25 : rem screen height
130 pc=42 : rem plot character '*'
140 gosub 1000
150 end
1000 rem plot line
1010 if abs(y1-y0)>abs(x1-x0) then se=1:tp=y0:y0=x0:x0=tp:tp=y1:y1=x1:x1=tp
1020 if x0>x1 then tp=x1:x1=x0:x0=tp:tp=y1:y1=y0:y0=tp
1030 dx=x1-x0
1040 dy=abs(y1-y0)
1050 er=dx/2
1060 y=y0
1070 ys=-1
1080 if y0<y1 then ys = 1
1090 for x=x0 to x1
1100 if se=1 then p0=y: p1=x:gosub 2000:goto 1120
1110 p0=x: p1=y: gosub 2000
1120 er=er-dy
1130 if er<0 then y=y+ys:er=er+dx
1140 next x
1150 return
2000 rem plot individual point
2010 rem p0 == plot point x
2020 rem p1 == plot point y
2030 sl=p0+(p1*sw)
2040 rem make sure we dont write beyond screen memory
2050 if sl<(sw*sh) then poke sc+sl,pc
2060 return
</syntaxhighlight>
[https://www.worldofchris.com/assets/c64-bresenham-line.png C64 Example screenshot]
=={{header|Common Lisp}}==
 
<langsyntaxhighlight lang="lisp">(defun draw-line (buffer x1 y1 x2 y2 pixel)
(declare (type rgb-pixel-buffer buffer))
(declare (type integer x1 y1 x2 y2))
(declare (type rgb-pixel pixel))
(let* ((dist-x (abs (- x1 x2)))
(dist-y (abs (- y1 y2)))
(steep (> dist-y dist-x)))
(when steep
(psetf x1 y1 y1 x1
x2 y2 y2 x2))
(when (> x1 x2)
(psetf x1 x2 x2 x1
y1 y2 y2 y1))
(let* ((delta-x (- x2 x1))
(delta-y (abs (- y1 y2)))
(error (floor delta-x 2))
(y-step (if (< y1 y2) 1 -1))
(y y1))
(loop
:for x :upfrom x1 :to x2
:do (progn (if steep
(setf (rgb-pixel buffer x y) pixel)
(setf (rgb-pixel buffer y x) pixel))
(setf error (- error delta-y))
(when (< error 0)
(incf y y-step)
(incf error delta-x)))))
buffer))</langsyntaxhighlight>
 
=={{header|D}}==
This code uses the Image defined in [[Bitmap]] Task.
 
<syntaxhighlight lang="d">module bitmap_bresenhams_line_algorithm;
This example uses Bitmap structure template defined in [[Basic bitmap storage]] task.
 
import std.algorithm, std.math, bitmap;
This version uses direct pointers to the data to speed things up.
 
void drawLine(Color)(Image!Color img,
<lang D>// swap function template
void swap(T)(ref T a, ref T b) { T t = a; a = b; b = t; } size_t x1, size_t y1,
in size_t x2, in size_t y2,
// absolute value, this could be taken from std.math or
in Color color)
// tango.math.Math, but is placed here for convenience
pure nothrow @nogc {
T labs(T)(T a) { return a < 0 ? -a : a; }
immutable int dx = x2 - x1;
immutable int ix = (dx > 0) - (dx < 0);
immutable size_t dx2 = abs(dx) * 2;
int dy = y2 - y1;
immutable int iy = (dy > 0) - (dy < 0);
immutable size_t dy2 = abs(dy) * 2;
img[x1, y1] = color;
 
if (dx2 >= dy2) {
void drawLine(T)(Bitmap!(T) dest, int x0, int y0, int x1, int y1, T color)
int error = dy2 - (dx2 / 2);
{
auto deltaY = labs while (y1x1 -!= y0x2); {
if (error >= 0 && (error || (ix > 0))) {
auto deltaX = labs(x1 - x0);
auto skew = deltaX > deltaY ? 1 : 0 error -= dx2;
y1 += iy;
}
 
if (! skew ) { error += dy2;
swap (deltaX, deltaY) x1 += ix;
swap (x0 img[x1, y0)y1] = color;
swap (x1, y1);}
} else {
int error = dx2 - (dy2 / 2);
 
auto d = while (deltaYy1 <<!= 1y2) - deltaX;{
if (error >= 0 && (error || (iy > 0))) {
deltaX = (deltaY - deltaX) << 1;
deltaY << error -= 1dy2;
x1 += ix;
}
 
if (x1 < x0) { error += dx2;
swap (x0, x1) y1 += iy;
swap (y0 img[x1, y1)] = color;
}
}
}
 
version (bitmap_bresenhams_line_algorithm_main) {
int step = (x0 < x1 && y0 < y1) ? 1 : -1;
ifvoid main(skew) {
Tauto *ptrimg = &dest.data[y0*dest.widthnew +Image!RGB(25, x0]22);
for img.drawLine(;5, x05, <15, x1; x0++20, ptr++RGB.white) {;
img.drawLine(3, 20, 10, 12, *ptr = colorRGB.white);
d += img.textualShow(d < 0) ? deltaY : deltaX;
if (d >= 0)
ptr += step*dest.width;
}
} else {
T *ptr = &dest.data[x0*dest.width + y0];
for (; x0 < x1; x0++, ptr+=dest.width) {
*ptr = color;
d += (d < 0) ? deltaY : deltaX;
if (d >= 0)
ptr += step;
}
 
}
}</langsyntaxhighlight>
To run the demo code compile with <code>-version=bitmap_bresenhams_line_algorithm_main</code>.
{{out}}
<pre>#########################
#########################
#########################
#########################
#########################
#####.###################
######.##################
######.##################
#######.#################
########.################
########.################
#########.###############
##########.##############
#########..##############
########.##.#############
#######.####.############
######.#####.############
######.######.###########
#####.########.##########
####.#########.##########
###.###########.#########
#########################</pre>
=={{header|Delphi}}==
 
<syntaxhighlight lang="delphi">
Sample usage:
procedure drawLine (bitmap : TBitmap; xStart, yStart, xEnd, yEnd : integer; color : TAlphaColor);
<lang D>Rgb black;
// Bresenham's Line Algorithm. Byte, March 1988, pp. 249-253.
Rgb yellow = {[255, 255, 0]};
// Modified from http://www.efg2.com/Lab/Library/Delphi/Graphics/Bresenham.txt and tested.
auto foobar = RgbBitmap(200, 100);
var
drawLine(foobar, 20, 20, 180, 80, yellow);
a, b : integer; // displacements in x and y
drawLine(foobar, 180, 20, 20, 80, yellow);</lang>
d : integer; // decision variable
diag_inc : integer; // d's increment for diagonal steps
dx_diag : integer; // diagonal x step for next pixel
dx_nondiag : integer; // nondiagonal x step for next pixel
dy_diag : integer; // diagonal y step for next pixel
dy_nondiag : integer; // nondiagonal y step for next pixel
i : integer; // loop index
nondiag_inc: integer; // d's increment for nondiagonal steps
swap : integer; // temporary variable for swap
x,y : integer; // current x and y coordinates
begin
x := xStart; // line starting point}
y := yStart;
// Determine drawing direction and step to the next pixel.
a := xEnd - xStart; // difference in x dimension
b := yEnd - yStart; // difference in y dimension
// Determine whether end point lies to right or left of start point.
if a < 0 then // drawing towards smaller x values?
begin
a := -a; // make 'a' positive
dx_diag := -1
end
else
dx_diag := 1;
 
// Determine whether end point lies above or below start point.
if b < 0 then // drawing towards smaller x values?
begin
b := -b; // make 'a' positive
dy_diag := -1
end
else
dy_diag := 1;
// Identify octant containing end point.
if a < b then
begin
swap := a;
a := b;
b := swap;
dx_nondiag := 0;
dy_nondiag := dy_diag
end
else
begin
dx_nondiag := dx_diag;
dy_nondiag := 0
end;
d := b + b - a; // initial value for d is 2*b - a
nondiag_inc := b + b; // set initial d increment values
diag_inc := b + b - a - a;
for i := 0 to a do
begin /// draw the a+1 pixels
drawPixel (bitmap, x, y, color);
if d < 0 then // is midpoint above the line?
begin // step nondiagonally
x := x + dx_nondiag;
y := y + dy_nondiag;
d := d + nondiag_inc // update decision variable
end
else
begin // midpoint is above the line; step diagonally}
x := x + dx_diag;
y := y + dy_diag;
d := d + diag_inc
end;
end;
end;
</syntaxhighlight>
=={{header|E}}==
 
{{trans|C}}
 
<langsyntaxhighlight lang="e">def swap(&left, &right) { # From [[Generic swap]]
def t := left
left := right
Line 370 ⟶ 1,469:
}
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="e">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>))</langsyntaxhighlight>
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=XZHNboMwEITvPMUeG0W4NrSHSnHehQRHQkoJMiRl3z6zePkrAsv7MTNe2118XKnrw0AjMRkyGRH9Pl4B9Sd9gWEUFsN1IGuK72nITNaJs47V371pobbElkZH7OaUeiRP1aWnD+AcioPQXmjuZNrcxHaCS6r531SkAJ4DWAJYA3gbwBLASwDvAkKMokVO3byoUAv6OiNbLUkDtkhM2m4XqkE16Xxkhwqe7dDchXjZctXW0odf+wgFKiRriUVBzuhkVKIL535tBA8Cjx6noMTs7KedVNxH6XtFnNy8dRtc1HJHhbXk5LUyXbmC6St/7N4AQOV/R7lxOJu9AQ== Run it]
 
{{trans|C}}
 
<syntaxhighlight>
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
</syntaxhighlight>
 
 
=={{header|Elm}}==
 
<syntaxhighlight lang="elm">
 
 
-- Brensenham Line Algorithm
 
type alias Position =
{x: Int, y: Int}
 
type alias BresenhamStatics =
{ finish : Position
, sx : Int
, sy : Int
, dx : Float
, dy : Float
}
 
 
line : Position -> Position -> List Position
line p q =
let
dx = (toFloat << abs) (q.x - p.x)
dy = (toFloat << abs) (q.y - p.y)
 
sx = if p.x < q.x then 1 else -1
sy = if p.y < q.y then 1 else -1
 
error =
(if dx > dy then dx else -dy) / 2
 
statics =
BresenhamStatics q sx sy dx dy
in
bresenhamLineLoop statics error p []
 
 
bresenhamLineLoop : BresenhamStatics -> Float -> Position -> List Position -> List Position
bresenhamLineLoop statics error p positions =
let
positions_ = p :: positions
{sx, sy, dx, dy, finish} = statics
in
if (p.x == finish.x) && (p.y == finish.y) then
positions_
else
let
(dErrX, x) =
if error > -dx then (-dy, sx + p.x)
else (0, p.x)
 
(dErrY, y) =
if error < dy then (dx, sy + p.y)
else (0, p.y)
 
error_ = error + dErrX + dErrY
in
bresenhamLineLoop statics error_ (Position x y) positions_
 
</syntaxhighlight>
 
=={{header|Erlang}}==
<langsyntaxhighlight lang="erlang">
build_path({Sx, Sy}, {Tx, Ty}) ->
if
Tx < Sx -> StepX = -1;
true -> StepX = 1
end,
if
Ty < Sy -> StepY = -1;
true -> StepY = 1
end,
Dx = abs((Tx-Sx)*2),
Dy = abs((Ty-Sy)*2),
if
Dy > 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) when F0 >= 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) when F0 < 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) when F0 >= 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) when F0 < 0 ->
Nx = Sx,
Ny = Sy + StepY,
F2 = F0 + Dx,
through_y({Nx, Ny}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F2, [{Nx, Ny}|P]).
</syntaxhighlight>
</lang>
OR
<langsyntaxhighlight lang="erlang">
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) when P0 < P1 ->
1;
step(_, _) ->
-1.
next_x(X, SX, DY, E, DE) when DE > -DY ->
{X + SX, E - DY};
next_x(X, _SX, _DY, E, _DE) ->
{X, E}.
 
next_y(Y, SY, DX, E, DE) when DE < DX ->
{Y + SY, E + DX};
next_y(Y, _SY, _DX, E, _DE) ->
{Y, E}.
</syntaxhighlight>
</lang>
=={{header|ERRE}}==
<syntaxhighlight lang="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
</syntaxhighlight>
=={{header|Euphoria}}==
 
{{trans|C}}
 
<syntaxhighlight lang="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.
--*/</syntaxhighlight>
Output:
<pre>
.......#........
......#.#.......
.....#...#......
....#..#..##....
...#..#.#...#...
..#..#...#...#..
.#..#.###.#...#.
#..#...#...#...#
.#..#.###.#...#.
..#..#...#...#..
...#..#.#...#...
....#..#...#....
....#.....#.....
.....#...#......
......#.#.......
.......#........
 
Press Any Key to continue...
</pre>
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let inline bresenham fill (x0, y0) (x1, y1) =
let steep = abs(y1 - y0) > abs(x1 - x0)
let x0, y0, x1, y1 =
Line 474 ⟶ 1,852:
else
loop (e-dy) (x+1) y
loop (dx/2) x0 y0</langsyntaxhighlight>
The following program tests the above bresenham function by drawing 100 lines into an image and visualizing the result using
{{libheader|Windows Presentation Foundation}}:
<langsyntaxhighlight lang="fsharp">open System.Windows
open System.Windows.Media.Imaging
 
Line 493 ⟶ 1,871:
BitmapSource.Create(n, n, 1.0, 1.0, format, null, pixel, n)
Window(Content=image, Title="Bresenham's line algorithm")
|> (Application()).Run |> ignore</langsyntaxhighlight>
 
=={{header|Factor}}==
A very ugly imperative implementation similar to the wikipedia pseudocode..
<langsyntaxhighlight lang="factor">USING: accessors arrays kernel locals math math.functions
math.ranges math.vectors rosettacode.raster.display
rosettacode.raster.storage sequences ui.gadgets ;
Line 533 ⟶ 1,910:
: draw-line ( {R,G,B} pt1 pt2 image -- )
[ line-points ] dip
[ set-pixel ] curry with each ;</langsyntaxhighlight>
=={{header|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:'''
<syntaxhighlight lang="qbasic">#DEFINE WM_LBUTTONDOWN 513
#DEFINE WM_CLOSE 16
 
FBSLSETTEXT(ME, "Bresenham") ' Set form caption
FBSLSETFORMCOLOR(ME, RGB(0, 255, 255)) ' Cyan: set persistent background color
DRAWWIDTH(5) ' Adjust point size
FBSL.GETDC(ME) ' Use volatile FBSL.GETDC below to avoid extra assignments
 
RESIZE(ME, 0, 0, 200, 235)
CENTER(ME)
SHOW(ME)
 
BEGIN EVENTS
SELECT CASE CBMSG
CASE WM_LBUTTONDOWN: Rhombus() ' Draw
CASE WM_CLOSE: FBSL.RELEASEDC(ME, FBSL.GETDC) ' Clean up
END SELECT
END EVENTS
 
SUB Rhombus()
Bresenham(50, 100, 100, 190)(100, 190, 150, 100)(150, 100, 100, 10)(100, 10, 50, 100)
SUB Bresenham(x0, y0, x1, y1)
DIM dx = ABS(x0 - x1), sx = SGN(x0 - x1)
DIM dy = ABS(y0 - y1), sy = SGN(y0 - y1)
DIM tmp, er = IIF(dx > dy, dx, -dy) / 2
WHILE NOT (x0 = x1 ANDALSO y0 = y1)
PSET(FBSL.GETDC, x0, y0, &HFF) ' Red: Windows stores colors in BGR order
tmp = er
IF tmp > -dx THEN: er = er - dy: x0 = x0 + sx: END IF
IF tmp < +dy THEN: er = er + dx: y0 = y0 + sy: END IF
WEND
END SUB
END SUB</syntaxhighlight>
'''Output:''' [[File:FBSLBresenham.PNG]]
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">defer steep \ noop or swap
defer ystep \ 1+ or 1-
 
Line 545 ⟶ 1,963:
2dup - abs >r
2over - abs r> <
if ['] swap \ swap use of x and y
else 2swap ['] noop
then is steep
( y0 y1 x0 x1 )
2dup >
if swap 2swap swap \ ensure x1 > x0
else 2swap
then
Line 583 ⟶ 2,001:
** *
**
ok</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
{{trans|C}}
<langsyntaxhighlight lang="fortran">module RCImagePrimitive
use RCImageBasic
 
Line 657 ⟶ 2,074:
end subroutine draw_line
 
end module RCImagePrimitive</langsyntaxhighlight>
 
Usage example:
 
<langsyntaxhighlight lang="fortran">program BasicImageTests
use RCImageBasic
use RCImageIO
Line 687 ⟶ 2,104:
call free_img(animage)
 
end program BasicImageTests</langsyntaxhighlight>
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' version 16-09-2015
' compile with: fbc -s console
' OR compile with: fbc -s gui
 
' Ported from the C version
Sub Br_line(x0 As Integer, y0 As Integer, x1 As Integer, y1 As Integer, Col As Integer = &HFFFFFF)
 
Dim As Integer dx = Abs(x1 - x0), dy = Abs(y1 - y0)
Dim As Integer sx = IIf(x0 < x1, 1, -1)
Dim As Integer sy = IIf(y0 < y1, 1, -1)
Dim As Integer er = IIf(dx > dy, dx, -dy) \ 2, e2
 
Do
PSet(x0, y0), col
If (x0 = x1) And (y0 = y1) Then Exit Do
e2 = er
If e2 > -dx Then Er -= dy : x0 += sx
If e2 < dy Then Er += dx : y0 += sy
Loop
 
End Sub
 
' ------=< MAIN >=------
 
Dim As Double x0, y0, x1, y1
 
ScreenRes 400, 400, 32
WindowTitle" Press key to end demo"
Randomize Timer
 
Do
Cls
For a As Integer = 1 To 20
Br_line(Rnd*380+10, Rnd*380+10, Rnd*380+10, Rnd*380+10, Rnd*&hFFFFFF)
Next
Sleep 2000
Loop Until InKey <> "" ' loop until a key is pressed
 
End</syntaxhighlight>
=={{header|Go}}==
<langsyntaxhighlight lang="go">package raster
 
// Line draws line by Bresenham's algorithm.
Line 734 ⟶ 2,191:
func (b *Bitmap) LineRgb(x0, y0, x1, y1 int, c Rgb) {
b.Line(x0, y0, x1, y1, c.Pixel())
}</langsyntaxhighlight>
A demonstration program:
<langsyntaxhighlight lang="go">package main
 
// Files required to build supporting package raster are found in:
Line 758 ⟶ 2,215:
fmt.Println(err)
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">module Bitmap.Line(line) where
 
import Bitmap
Line 793 ⟶ 2,249:
deltax = x2 - x1
deltay = abs $ y2 - y1
ystep = if y1 < y2 then 1 else -1</langsyntaxhighlight>
 
=={{header|J}}==
'''Solution:'''
 
Using definitions from [[Basic bitmap storage#J|Basic bitmap storage]].
<langsyntaxhighlight lang="j">thru=: <./ + -~ i.@+ _1 ^ > NB. integers from x through y
 
NB.*getBresenhamLine v Returns points for a line given start and end points
Line 814 ⟶ 2,269:
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 ]</langsyntaxhighlight>
 
'''Example Usage:'''
<langsyntaxhighlight lang="j"> myimg=: 0 255 0 makeRGB 20 32 NB. 32 by 20 green image
myimg=: ((1 1 ,: 5 11) ; 255 0 0 ) drawLines myimg NB. draw red line from xy point 1 1 to 11 5
 
Line 825 ⟶ 2,280:
viewRGB myimg=: (Diamond;255 0 0) drawLines myimg NB. draw 4 red lines to form a diamond
viewRGB myimg=: (Square;0 0 255) drawLines myimg NB. draw 4 blue lines to form a square
viewRGB (Diamond;255 0 0) drawLines (Square;0 0 255) drawLines myimg</langsyntaxhighlight>
=={{header|Java}}==
<syntaxhighlight lang="java">import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
 
public class Bresenham {
 
public static void main(String[] args) {
SwingUtilities.invokeLater(Bresenham::run);
}
 
private static void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setTitle("Bresenham");
 
f.getContentPane().add(new BresenhamPanel());
f.pack();
 
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
 
class BresenhamPanel extends JPanel {
 
private final int pixelSize = 10;
 
BresenhamPanel() {
setPreferredSize(new Dimension(600, 500));
setBackground(Color.WHITE);
}
 
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
 
int w = (getWidth() - 1) / pixelSize;
int h = (getHeight() - 1) / pixelSize;
int maxX = (w - 1) / 2;
int maxY = (h - 1) / 2;
int x1 = -maxX, x2 = maxX * -2 / 3, x3 = maxX * 2 / 3, x4 = maxX;
int y1 = -maxY, y2 = maxY * -2 / 3, y3 = maxY * 2 / 3, y4 = maxY;
 
drawLine(g, 0, 0, x3, y1); // NNE
drawLine(g, 0, 0, x4, y2); // ENE
drawLine(g, 0, 0, x4, y3); // ESE
drawLine(g, 0, 0, x3, y4); // SSE
drawLine(g, 0, 0, x2, y4); // SSW
drawLine(g, 0, 0, x1, y3); // WSW
drawLine(g, 0, 0, x1, y2); // WNW
drawLine(g, 0, 0, x2, y1); // NNW
}
 
private void plot(Graphics g, int x, int y) {
int w = (getWidth() - 1) / pixelSize;
int h = (getHeight() - 1) / pixelSize;
int maxX = (w - 1) / 2;
int maxY = (h - 1) / 2;
 
int borderX = getWidth() - ((2 * maxX + 1) * pixelSize + 1);
int borderY = getHeight() - ((2 * maxY + 1) * pixelSize + 1);
int left = (x + maxX) * pixelSize + borderX / 2;
int top = (y + maxY) * pixelSize + borderY / 2;
 
g.setColor(Color.black);
g.drawOval(left, top, pixelSize, pixelSize);
}
 
private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
// delta of exact value and rounded value of the dependent variable
int d = 0;
 
int dx = Math.abs(x2 - x1);
int dy = Math.abs(y2 - y1);
 
int dx2 = 2 * dx; // slope scaling factors to
int dy2 = 2 * dy; // avoid floating point
 
int ix = x1 < x2 ? 1 : -1; // increment direction
int iy = y1 < y2 ? 1 : -1;
 
int x = x1;
int y = 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;
}
}
}
}
}</syntaxhighlight>
=={{header|JavaScript}}==
Instead of swaps in the initialisation use error calculation for both directions x and y simultaneously:
<langsyntaxhighlight lang="javascript">function bline(x0, y0, x1, y1) {
 
var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
Line 842 ⟶ 2,412:
if (e2 < dy) { err += dx; y0 += sy; }
}
}</langsyntaxhighlight>
=={{header|Julia}}==
{{works with|Julia|0.6}}
<syntaxhighlight lang="julia">function drawline!(img::Matrix{T}, x0::Int, y0::Int, x1::Int, y1::Int, col::T) where T
δx = abs(x1 - x0)
δy = abs(y1 - y0)
δe = abs(δy / δx)
er = 0.0
 
y = y0
for x in x0:x1
img[x, y] = col
er += δe
if er > 0.5
y += 1
er -= 1.0
end
end
 
return img
end
 
using Images
 
img = 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()</syntaxhighlight>
 
{{out}}
<pre>
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) </pre>
 
=={{header|ksh}}==
<syntaxhighlight lang="ksh">function line {
typeset x0=$1 y0=$2 x1=$3 y1=$4
 
if ((x0 > x1))
then
((dx = x0 - x1)); ((sx = -1))
else
((dx = x1 - x0)); ((sx = 1))
fi
 
if ((y0 > y1))
then
((dy = y0 - y1)); ((sy = -1))
else
((dy = y1 - y0)); ((sy = 1))
fi
 
if ((dx > dy))
then
((err = dx))
else
((err = -dy))
fi
((err /= 2)); ((e2 = 0))
 
while :
do
echo $x0 $y0
((x0 == x1 && y0 == y1)) && return
((e2 = err))
((e2 > -dx)) && { ((err -= dy)); ((x0 += sx)) }
((e2 < dy)) && { ((err += dx)); ((y0 += sy)) }
done
}</syntaxhighlight>
Output from the statement:
line 0 0 3 4
(which could be piped to another program)
<pre>0 0
1 1
1 2
2 3
3 4</pre>
 
=={{header|Lua}}==
{{trans|C}}
{{works with|Lua 5.1 (or above, tested on: 5.1.5, 5.2.3, 5.3.5)}}
<syntaxhighlight lang="lua">
-----------------------------------------------
-- Bitmap replacement
-- (why? current Lua impl lacks a "set" method)
-----------------------------------------------
local Bitmap = {
new = function(self, width, height)
local instance = setmetatable({ width=width, height=height }, self)
instance:alloc()
return instance
end,
alloc = function(self)
self.pixels = {}
for y = 1, self.height do
self.pixels[y] = {}
for x = 1, self.width do
self.pixels[y][x] = 0x00000000
end
end
end,
clear = function(self, c)
for y = 1, self.height do
for x = 1, self.width do
self.pixels[y][x] = c or 0x00000000
end
end
end,
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)) then
return self.pixels[y][x]
else
return nil
end
end,
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)) then
self.pixels[y][x] = c or 0x00000000
end
end,
}
Bitmap.__index = Bitmap
setmetatable(Bitmap, { __call = function (t, ...) return t:new(...) end })
 
------------------------------
-- Bresenham's Line Algorithm:
------------------------------
Bitmap.line = function(self, x1, y1, x2, y2, c)
local dx, sx = math.abs(x2-x1), x1<x2 and 1 or -1
local dy, sy = math.abs(y2-y1), y1<y2 and 1 or -1
local err = math.floor((dx>dy and dx or -dy)/2)
while(true) do
self:set(x1, y1, c or 0xFFFFFFFF)
if (x1==x2 and y1==y2) then break end
if (err > -dx) then
err, x1 = err-dy, x1+sx
if (x1==x2 and y1==y2) then
self:set(x1, y1, c or 0xFFFFFFFF)
break
end
end
if (err < dy) then
err, y1 = err+dx, y1+sy
end
end
end
 
--------
-- Demo:
--------
Bitmap.render = function(self, charmap)
for y = 1, self.height do
local rowtab = {}
for x = 1, self.width do
rowtab[x] = charmap[self.pixels[y][x]]
end
print(table.concat(rowtab))
end
end
local bitmap = 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'})</syntaxhighlight>
{{out}}<pre>.............................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.............................
</pre>
=={{header|Maple}}==
 
<langsyntaxhighlight lang="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;
Line 881 ⟶ 2,654:
end do;
return img2;
end proc:</langsyntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">Rasterize[Style[Graphics[Line[{{0, 0}, {20, 10}}]], Antialiasing -> False]]</syntaxhighlight>
=={{header|MATLAB}}==
Note: Store this function in a file named "bresenhamLine.m" in the @Bitmap folder for the Bitmap class defined [[Bitmap#MATLAB|here]].
[[File:Bresenham.png|thumb|MATLAB sample usage output.]]
<syntaxhighlight lang="matlab">
%screen = Bitmap object
%startPoint = [x0,y0]
%endPoint = [x1,y1]
%color = [red,green,blue]
 
function bresenhamLine(screen,startPoint,endPoint,color)
 
if( any(color > 255) )
error 'RGB colors must be between 0 and 255';
end
 
%Check for vertical line, x0 == x1
if( startPoint(1) == endPoint(1) )
%Draw vertical line
for i = (startPoint(2):endPoint(2))
setPixel(screen,[startPoint(1) i],color);
end
end
 
%Simplified Bresenham algorithm
dx = abs(endPoint(1) - startPoint(1));
dy = abs(endPoint(2) - startPoint(2));
if(startPoint(1) < endPoint(1))
sx = 1;
else
sx = -1;
end
if(startPoint(2) < endPoint(2))
sy = 1;
else
sy = -1;
end
err = dx - dy;
pixel = startPoint;
while(true)
screen.setPixel(pixel,color); %setPixel(x0,y0)
if( pixel == endPoint )
break;
end
e2 = 2*err;
if( e2 > -dy )
err = err - dy;
pixel(1) = pixel(1) + sx;
end
if( e2 < dx )
err = err + dx;
pixel(2) = pixel(2) + sy;
end
end
assignin('caller',inputname(1),screen); %saves the changes to the object
end
</syntaxhighlight>
 
Sample Usage:
<syntaxhighlight lang="matlab">
>> img = Bitmap(800,600);
>> img.bresenhamLine([400 550],[200 400],[255 255 255]);
>> img.bresenhamLine([400 550],[600 400],[255 255 255]);
>> img.bresenhamLine([200 400],[350 150],[255 255 255]);
>> img.bresenhamLine([600 400],[450 150],[255 255 255]);
>> img.bresenhamLine([350 150],[450 150],[255 255 255]);
>> img.bresenhamLine([400 550],[400 150],[255 255 255]);
>> disp(img)
</syntaxhighlight>
=={{header|MAXScript}}==
 
<langsyntaxhighlight lang="maxscript">fn plot img coord steep col =
(
if steep then
Line 897 ⟶ 2,749:
(
local steep = (abs (end.y - start.y)) > (abs (end.x - start.x))
if steep then
(
Line 903 ⟶ 2,755:
swap end.x end.y
)
if start.x > end.x then
(
Line 909 ⟶ 2,761:
swap start.y end.y
)
local deltaX = end.x - start.x
local deltaY = abs (end.y - start.y)
Line 915 ⟶ 2,767:
local yStep = -1
local y = start.y
if start.y < end.y then
(
yStep = 1
)
for x in start.x to end.x do
(
Line 936 ⟶ 2,788:
myBitmap = bitmap 512 512 color:(color 0 0 0)
myBitmap = drawLine myBitmap [0, 511] [511, 0] #((color 255 255 255))
display myBitmap</langsyntaxhighlight>
=={{header|Metal}}==
 
For drawing lines between points in an Apple Metal compute shader.
 
<syntaxhighlight lang="metal">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;
}
}
}</syntaxhighlight>
 
=={{header|MiniScript}}==
This GUI implementation is for use with [http://miniscript.org/MiniMicro Mini Micro].
<syntaxhighlight lang="miniscript">
drawLine = function(img, x0, y0, x1, y1, colr)
sign = function(a, b)
if a < b then return 1
return -1
end function
dx = abs(x1 - x0)
sx = sign(x0, x1)
dy = abs(y1 - y0)
sy = sign(y0, y1)
if dx > dy then
err = dx
else
err = -dy
end if
err = floor(err / 2)
while true
img.setPixel x0, y0, colr
if x0 == x1 and y0 == y1 then break
e2 = err
if e2 > -dx then
err -= dy
x0 += sx
end if
if e2 < dy then
err += dx
y0 += sy
end if
end while
end function
 
img= Image.create(320, 320)
drawLine img, 0, 0, 250, 300, color.red
gfx.clear
gfx.drawImage img, 0, 0
</syntaxhighlight>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import bitmap
 
proc drawLine*(img: Image; p, q: Point; color: Color) =
let
dx = abs(q.x - p.x)
sx = if p.x < q.x: 1 else: -1
dy = abs(q.y - p.y)
sy = if p.y < q.y: 1 else: -1
 
var
p = p
q = q
err = (if dx > dy: dx else: -dy) div 2
e2 = 0
 
while true:
img[p.x, p.y] = color
if p == q:
break
e2 = err
if e2 > -dx:
err -= dy
p.x += sx
if e2 < dy:
err += dx
p.y += sy
 
when isMainModule:
var img = 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()</syntaxhighlight>
 
{{out}}
<pre>.......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........</pre>
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">let draw_line ~img ~color ~p0:(x0,y0) ~p1:(x1,y1) =
 
let steep = abs(y1 - y0) > abs(x1 - x0) in
Line 979 ⟶ 2,971:
in
loop x0 y0 error
;;</langsyntaxhighlight>
=={{header|Pascal}}==
 
[[Bresenham's_line_algorithm#Delphi | Delphi]]
=={{header|Perl}}==
 
{{libheader|Imlib2}}
 
<langsyntaxhighlight lang="perl">#! /usr/bin/perl
use strict;
use Image::Imlib2;
Line 995 ⟶ 2,989:
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;
Line 1,010 ⟶ 3,004:
$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;
}
}
}
Line 1,047 ⟶ 3,041:
$img->save("test1.png");
 
exit 0;</langsyntaxhighlight>
 
Images <tt>test0.png</tt> and <tt>test1.png</tt> look different since Imlib2 draw lines with antialiasing.
=={{header|Phix}}==
Modified copy of [[Bitmap/Bresenham%27s_line_algorithm#Euphoria|Euphoria]], with a bigger bitmap and a simpler pattern.
Requires new_image() from [[Bitmap#Phix|Bitmap]], write_ppm() from [[Bitmap/Write_a_PPM_file#Phix|Write_a_PPM_file]]. <br>
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
<syntaxhighlight lang="phix">-- demo\rosetta\Bresenham_line.exw (runnable version)
 
global function bresLine(sequence image, integer x0, y0, x1, y1, colour)
-- The line algorithm
integer dimx = 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)
while true do
if x0>=1 and x0<=dimx
and y0>=1 and y0<=dimy then
image[x0][y0] = colour
end if
if x0=x1 and y0=y1 then exit end if
prevle = lineError
if prevle>-deltaX then
lineError -= deltaY
x0 += stepX
end if
if prevle<deltaY then
lineError += deltaX
y0 += stepY
end if
end while
return image
end function
 
--include ppm.e -- red, green, blue, white, new_image(), write_ppm(), bresLine() (as distributed, instead of the above)
 
sequence screenData = 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)</syntaxhighlight>
=={{header|PicoLisp}}==
<syntaxhighlight lang="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) ) )</syntaxhighlight>
=={{header|PL/I}}==
===version 1===
<lang PL/I>
{{incorrect|PL/I|The sample output does not start at -1/-3!?! Pls show the complete program producing this output.}}
/* Draw a line fom (x0, y0) to (x1, y1). 13 May 2010 */
<syntaxhighlight lang="pl/i">
/* 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;
Line 1,085 ⟶ 3,168:
 
end draw_line;
</syntaxhighlight>
</lang>
 
Output from the statement:-
call draw_line(-1, -3, 6, 10);
for a -10:10 x -10:10 grid:
<syntaxhighlight lang="text">
..........|..........
..........|..........
Line 1,112 ⟶ 3,195:
..........|..........
..........|..........
</syntaxhighlight>
</lang>
 
===version 2===
=={{header|PicoLisp}}==
<syntaxhighlight lang="pl/i">*process source xref or(!);
<lang PicoLisp>(de brez (Img X Y DX DY)
brbn:Proc Options(main);
(let SX
/*********************************************************************
(cond
* 21.05.2014 Walter Pachl
((=0 DX) 0)
* Implementing the pseudo code of
((gt0 DX) 1)
* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
(T (setq DX (- DX)) -1) )
* under 'Simplification' (see also REXX version 2)
(let SY
*********************************************************************/
(cond
grid.=
((=0 DY) 0)
dcl image(-2:7,-4:11) char(1);
((gt0 DY) 1)
image='.';
(T (setq DY (- DY)) -1) )
image(*,0)='-';
(if (>= DX DY)
image(0,*)='|';
(let E (- (* 2 DY) DX)
image(0,0)='+';
(do DX
call draw_line(-1,-3,6,10);
(set (nth Img Y X) 1)
Dcl (i,j) Bin Fixed(31);
(when (ge0 E)
Do j=11 To -4 By -1;
(inc 'Y SY)
Put Edit(decj,' 'E )(Skip,f(* 2 DX),a) );
Do i=-2 To 7;
(inc 'X SX)
Put Edit(inc 'E image(* 2 DYi,j)) ) (a);
End;
(let E (- (* 2 DX) DY)
End;
(do DY
Put Edit(' 2101234567')(Skip,a);
(set (nth Img Y X) 1)
 
(when (ge0 E)
draw_line: procedure (x0,y0,x1,y1);
(inc 'X SX)
dcl (x0,y0,x1,y1) fixed binary(31);
(dec 'E (* 2 DY)) )
dcl (dx,dy,sx,sy,err,e2) fixed binary(31);
(inc 'Y SY)
 
(inc 'E (* 2 DX)) ) ) ) ) ) )
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;</syntaxhighlight>
'''output'''
<pre>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</pre>
=={{header|Prolog}}==
 
 
<syntaxhighlight lang="prolog">
:- use_module(bitmap).
:- use_module(bitmapIO).
:- use_module(library(clpfd)).
 
% ends when X1 = X2 and Y1 = Y2
draw_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).
 
(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) ) )</lang>
 
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).
</syntaxhighlight>
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure BresenhamLine(x0 ,y0 ,x1 ,y1)
If Abs(y1 - y0) > Abs(x1 - x0);
steep =#True
Line 1,214 ⟶ 3,367:
Until Event = #PB_Event_CloseWindow
EndIf
EndIf</langsyntaxhighlight>
 
=={{header|Python}}==
{{works with|Python|3.1}}
Line 1,221 ⟶ 3,373:
Extending the example given [[Basic_bitmap_storage/Python#Alternative_version|here]] and using the algorithm from the Ada solution:
 
<langsyntaxhighlight lang="python">def line(self, x0, y0, x1, y1):
"Bresenham's line algorithm"
dx = abs(x1 - x0)
Line 1,278 ⟶ 3,430:
| |
+-----------------+
'''</langsyntaxhighlight>
 
===Not relying on floats===
Extending the example given [[Basic_bitmap_storage/Python#Alternative_version|here]].
 
<syntaxhighlight lang="python">
from fractions import Fraction
 
def line(self, x0, y0, x1, y1):
rev = reversed
if abs(y1 - y0) <= abs(x1 - x0):
x0, y0, x1, y1 = y0, x0, y1, x1
rev = lambda x: x
if x1 < x0:
x0, y0, x1, y1 = x1, y1, x0, y0
leny = abs(y1 - y0)
for i in range(leny + 1):
self.set(*rev((round(Fraction(i, leny) * (x1 - x0)) + x0, (1 if y1 > y0 else -1) * i + y0)))
 
Bitmap.line = line
 
# see test code above
</syntaxhighlight>
=={{header|Racket}}==
Port of the Python version.
<syntaxhighlight lang="racket">
#lang racket
(require racket/draw)
 
(define (draw-line dc x0 y0 x1 y1)
(define dx (abs (- x1 x0)))
(define dy (abs (- y1 y0)))
(define sx (if (> x0 x1) -1 1))
(define sy (if (> y0 y1) -1 1))
(cond
[(> dx dy)
(let loop ([x x0] [y y0] [err (/ dx 2.0)])
(unless (= x x1)
(send dc draw-point x y)
(define newerr (- err dy))
(if (< newerr 0)
(loop (+ x sx) (+ y sy) (+ newerr dx))
(loop (+ x sx) y newerr))))]
[else
(let loop ([x x0] [y y0] [err (/ dy 2.0)])
(unless (= y y1)
(send dc draw-point x y)
(define newerr (- err dy))
(if (< newerr 0)
(loop (+ x sx) (+ y sy) newerr)
(loop x (+ y sy) (+ newerr dy)))))]))
 
(define bm (make-object bitmap% 17 17))
(define dc (new bitmap-dc% [bitmap bm]))
(send dc set-smoothing 'unsmoothed)
(send dc set-pen "red" 1 'solid)
(for ([points '((1 8 8 16) (8 16 16 8) (16 8 8 1) (8 1 1 8))])
(apply draw-line (cons dc points)))
bm
</syntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.03}}
Bitmap class from [[Bitmap#Raku|Bitmap]] task.
<syntaxhighlight lang="raku" line>class Pixel { has UInt ($.R, $.G, $.B) }
class Bitmap {
has UInt ($.width, $.height);
has Pixel @!data;
method fill(Pixel $p) {
@!data = $p.clone xx ($!width*$!height)
}
method pixel(
$i where ^$!width,
$j where ^$!height
--> Pixel
) is rw { @!data[$i + $j * $!width] }
method set-pixel ($i, $j, Pixel $p) {
self.pixel($i, $j) = $p.clone;
}
method get-pixel ($i, $j) returns Pixel {
self.pixel($i, $j);
}
}
sub line(Bitmap $bitmap, $x0 is copy, $x1 is copy, $y0 is copy, $y1 is copy) {
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;
}
}
}</syntaxhighlight>
=={{header|RapidQ}}==
 
Use this routine together with the code from [[Basic_bitmap_storage#RapidQ|Basic bitmap storage]] to create a full application.
 
<langsyntaxhighlight lang="rapidq">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</langsyntaxhighlight>
 
Example usage:
 
<langsyntaxhighlight lang="rapidq">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</langsyntaxhighlight>
=={{header|REXX}}==
=== version 1 ===
This REXX version has automatic scaling (for displaying the plot), &nbsp; includes a
border, &nbsp; accepts lines segments from the
<br>command line, &nbsp; displays a (background) plot field, &nbsp; uses an infinite field, &nbsp; and
it also handles multiple line segments.
<syntaxhighlight lang="rexx">/*REXX program plots/draws line segments using the Bresenham's line (2D) algorithm. */
parse arg data /*obtain optional arguments from the CL*/
if data='' then data= "(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).*/
do points=1 while data\='' /*put the data points into an array (!)*/
parse var data x y data; !.points=x y /*extract the line segments. */
if points==1 then do; minX= x; maxX= x; minY= y; maxY= y /*1st case.*/
end
minX= 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 " " " " */
 
do x=minX to maxX; @.x.0= '─'; end /*draw a dash from left ───► right.*/
do y=minY to maxY; @.0.y= '│'; end /*draw a pipe from lowest ───► highest*/
@.0.0= '┼' /*define the plot's origin axis point. */
do seg=2 to points-1; _= seg - 1 /*obtain the X and Y line coördinates*/
call drawLine !._, !.seg /*draw (plot) a line segment. */
end /*seg*/ /* [↑] drawing the line segments. */
/* [↓] display the plot to terminal. */
do y=maxY to minY by -1; _= /*display the plot one line at a time. */
do x=minX to maxX; _= _ || @.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: procedure expose @.; parse arg x y,xf yf; parse value '-1 -1' with sx sy
dx= abs(xf-x); if x<xf then sx= 1 /*obtain X range, determine the slope*/
dy= abs(yf-y); if y<yf then sy= 1 /* " Y " " " " */
err= dx - dy /*calculate error between adjustments. */
/*Θ is the plot character for points. */
do forever; @.x.y= 'Θ' /*plot the points until it's complete. */
if x=xf & y=yf then return /*are the plot points at the finish? */
err2= err + err /*calculate double the error value. */
if err2 > -dy then do; err= err - dy; x= x + sx; end
if err2 < dx then do; err= err + dx; y= y + sy; end
end /*forever*/</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
···│····················
···│····················
···│·······Θ············
···│······Θ·Θ···········
···│·····Θ···Θ··········
···│····Θ·····Θ·········
···│···Θ·······Θ········
···│···Θ········Θ·······
···│··Θ··········Θ······
···│·Θ············Θ·····
···│Θ··············Θ····
···│·Θ············Θ·····
···│··Θ··········Θ······
···│···Θ·······ΘΘ·······
···│····Θ·····Θ·········
···│·····Θ···Θ··········
···│······Θ·Θ···········
···│·······Θ············
───┼────────────────────
···│····················
</pre>
 
=== version 2 ===
<syntaxhighlight lang="rexx">/* REXX ***************************************************************
* 21.05.2014 Walter Pachl
* Implementing the pseudo code of
* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
* under 'Simplification'
**********************************************************************/
grid.='.'
Do i=-2 To 7; grid.i.0='-'; End
Do j=-4 To 11; grid.0.j='|'; End
grid.0.0='+'
Call line -1,-3,6,10
Do j=11 To -4 By -1
ol=format(j,2)' '
Do i=-2 To 7
ol=ol||grid.i.j
End
Say ol
End
Say ' 2101234567'
Exit
line: Procedure Expose grid.
Parse Arg x0, y0, x1, y1
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 Forever
grid.x0.y0='X'
if x0 = x1 & y0 = y1 Then Leave
e2 = 2*err
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
Return</syntaxhighlight>
'''output'''
<pre>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</pre>
=={{header|Ring}}==
<syntaxhighlight lang="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() }
</syntaxhighlight>
Output :
[https://lh3.googleusercontent.com/-6uJvON0dAuo/V2LO2zz4zQI/AAAAAAAAALE/IjEGFuhta6oUSeG2QfuxcPBWMmCyNCjdwCLcB/s1600/CalmoSoftBresenham.jpg Bitmap/Bresenham's algorithm]
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">Pixel = Struct.new(:x, :y)
 
class Pixmap
Line 1,377 ⟶ 3,836:
bitmap.draw_line(Pixel[10, 10], Pixel[a,490], RGBColour::YELLOW)
end
bitmap.draw_line(Pixel[10, 10], Pixel[490,490], RGBColour::YELLOW)</langsyntaxhighlight>
=={{header|Rust}}==
<syntaxhighlight lang="rust">
struct Point {
x: i32,
y: i32
}
 
fn main() {
let mut points: Vec<Point> = Vec::new();
points.append(&mut get_coordinates(1, 20, 20, 28));
points.append(&mut get_coordinates(20, 28, 69, 0));
draw_line(points, 70, 30);
}
 
fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<Point> {
let mut coordinates: Vec<Point> = vec![];
let dx:i32 = i32::abs(x2 - x1);
let dy:i32 = i32::abs(y2 - y1);
let sx:i32 = { if x1 < x2 { 1 } else { -1 } };
let sy:i32 = { if y1 < y2 { 1 } else { -1 } };
 
let mut error:i32 = (if dx > dy { dx } else { -dy }) / 2 ;
let mut current_x:i32 = x1;
let mut current_y:i32 = y1;
loop {
coordinates.push(Point { x : current_x, y: current_y });
 
if current_x == x2 && current_y == y2 { break; }
 
let error2:i32 = error;
 
if error2 > -dx {
error -= dy;
current_x += sx;
}
if error2 < dy {
error += dx;
current_y += sy;
}
}
coordinates
}
 
fn draw_line(line: std::vec::Vec<Point>, width: i32, height: i32) {
for col in 0..height {
for row in 0..width {
let is_point_in_line = line.iter().any(| point| point.x == row && point.y == col);
match is_point_in_line {
true => print!("@"),
_ => print!(".")
};
}
print!("\n");
}
}
</syntaxhighlight>
'''Output:'''
<pre>
.....................................................................@
...................................................................@@.
.................................................................@@...
...............................................................@@.....
..............................................................@.......
............................................................@@........
..........................................................@@..........
........................................................@@............
.......................................................@..............
.....................................................@@...............
...................................................@@.................
.................................................@@...................
................................................@.....................
..............................................@@......................
............................................@@........................
..........................................@@..........................
.........................................@............................
.......................................@@.............................
.....................................@@...............................
...................................@@.................................
.@@...............................@...................................
...@@...........................@@....................................
.....@@.......................@@......................................
.......@@@..................@@........................................
..........@@...............@..........................................
............@@@..........@@...........................................
...............@@......@@.............................................
.................@@..@@...............................................
...................@@.................................................
......................................................................
</pre>
=={{header|Scala}}==
Uses the [[Basic_bitmap_storage#Scala|Scala Basic Bitmap Storage]] class.
<langsyntaxhighlight lang="scala">object BitmapOps {
def bresenham(bm:RgbBitmap, x0:Int, y0:Int, x1:Int, y1:Int, c:Color)={
val dx=math.abs(x1-x0)
Line 1,398 ⟶ 3,945:
res;
}
def hasNext = (sx*x <= sx*x1 && sy*y <= sy*y1)
}
 
for((x,y) <- it)
bm.setPixel(x, y, c)
}
}</langsyntaxhighlight>
=={{header|Sidef}}==
{{trans|Perl}}
<syntaxhighlight lang="ruby">func my_draw_line(img, x0, y0, x1, y1) {
 
var 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)
}
 
var deltax = (x1 - x0)
var deltay = abs(y1 - y0)
var error = (deltax / 2)
var y = y0
var ystep = (y0 < y1 ? 1 : -1)
 
x0.to(x1).each { |x|
img.draw_point(steep ? ((y, x)) : ((x, y)))
error -= deltay
if (error < 0) {
y += ystep
error += deltax
}
}
}
 
require('Image::Imlib2')
 
var img = %s'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) # black
my_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")</syntaxhighlight>
 
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma annotate( 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" );
pragma license( unrestricted );
 
pragma restriction( no_external_commands );
 
procedure drawline is
 
-- Spar 1.x has only single-dimensional arrays but we can simulate a
-- two dimensional array that has been folded into a 1D array
 
width : constant positive := 20;
height : constant positive := 20;
type image_array is array(1..400) of character;
Picture : image_array;
 
-- Line
-- Draw a line between two coordinates using the given character
 
procedure Line ( 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 : constant float := abs( float( Stop_X ) - float( Start_X ) );
DY : constant float := 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;
begin
if Start_X > Stop_X then
Step_X := -1;
end if;
if Start_Y > Stop_Y then
Step_Y := -1;
end if;
if DX > DY then
Err := DX / 2.0;
while X /= Stop_X loop
Picture (X + width*(Y-1)) := Color;
Err := @ - DY;
if Err < 0.0 then
Y := positive( integer(@) + Step_Y);
Err := @ + DX;
end if;
X := positive( integer(@) + Step_X );
end loop;
else
Err := DY / 2.0;
while Y /= Stop_Y loop
Picture (X + height*(Y-1)) := Color;
Err := @ - DX;
if Err < 0.0 then
X := positive( integer(@) + Step_X );
Err := @ + DY;
end if;
Y := positive( integer(@) + Step_Y );
end loop;
end if;
Picture (X + width*(Y-1)) := Color;
end Line;
 
-- new_picture
-- Erase the picture by filling it with spaces.
 
procedure new_picture is
begin
for i in arrays.first( Picture )..arrays.last( Picture ) loop
Picture(i) := ' ';
end loop;
end new_picture;
 
-- render
-- Draw the contents of the picture area.
 
procedure render is
begin
for i in arrays.first( Picture )..arrays.last( Picture ) loop
put( Picture(i) );
if i mod width = 0 then
new_line;
end if;
end loop;
end render;
 
begin
new_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;
end drawline;</syntaxhighlight>
 
=={{header|Tcl}}==
{{libheader|Tk}}
ref [[Basic bitmap storage#Tcl]]
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require Tk
 
Line 1,447 ⟶ 4,150:
fill $img black
drawLine $img yellow {20 20} {180 80}
drawLine $img yellow {180 20} {20 80}</langsyntaxhighlight>
 
=={{header|TI-89 BASIC}}==
 
Line 1,455 ⟶ 4,157:
{{trans|E}}
 
<langsyntaxhighlight lang="ti89b">(lx0, ly0, lx1, ly1)
Prgm
Local steep, x, y, dx, dy, ystep, error, tmp
Line 1,488 ⟶ 4,190:
EndIf
EndFor
EndPrgm</langsyntaxhighlight>
=={{header|VBScript}}==
{{trans|Rexx}}
<syntaxhighlight lang="vb">'Bitmap/Bresenham's line algorithm - VBScript - 13/05/2019
Dim map(48,40), list(10), ox, oy
data=Array(1,8, 8,16, 16,8, 8,1, 1,8)
For i=0 To UBound(map,1): For j=0 To UBound(map,2)
map(i,j)="."
Next: Next 'j, i
points=(UBound(data)+1)/2
For p=1 To points
x=data((p-1)*2)
y=data((p-1)*2+1)
list(p)=Array(x,y)
If p=1 Then minX=x: maxX=x: minY=y: maxY=y
If x<minX Then minX=x
If x>maxX Then maxX=x
If y<minY Then minY=y
If y>maxY Then maxY=y
Next 'p
border=2
minX=minX-border*2 : maxX=maxX+border*2
minY=minY-border : maxY=maxY+border
ox =-minX : oy =-minY
wx=UBound(map,1)-ox : If maxX>wx Then maxX=wx
wy=UBound(map,2)-oy : If maxY>wy Then maxY=wy
For x=minX To maxX: map(x+ox,0+oy)="-": Next 'x
For y=minY To maxY: map(0+ox,y+oy)="|": Next 'y
map(ox,oy)="+"
For p=1 To points-1
draw_line list(p), list(p+1)
Next 'p
For y=maxY To minY Step -1
line=""
For x=minX To maxX
line=line & map(x+ox,y+oy)
Next 'x
Wscript.Echo line
Next 'y
 
Sub draw_line(p1, p2)
Dim x,y,xf,yf,dx,dy,sx,sy,err,err2
x =p1(0) : y =p1(1)
xf=p2(0) : yf=p2(1)
dx=Abs(xf-x) : dy=Abs(yf-y)
If x<xf Then sx=+1: Else sx=-1
If y<yf Then sy=+1: Else sy=-1
err=dx-dy
Do
map(x+ox,y+oy)="X"
If x=xf And y=yf Then Exit Do
err2=err+err
If err2>-dy Then err=err-dy: x=x+sx
If err2< dx Then err=err+dx: y=y+sy
Loop
End Sub 'draw_line </syntaxhighlight>
{{out}}
<pre>
...|....................
...|....................
...|.......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............
---+--------------------
...|....................
</pre>
=={{header|Vedit macro language}}==
 
<langsyntaxhighlight lang="vedit">// 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</langsyntaxhighlight>
=={{header|Wart}}==
<syntaxhighlight lang="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</syntaxhighlight>
=={{header|Wren}}==
{{libheader|DOME}}
Requires version 1.3.0 of DOME or later.
<syntaxhighlight lang="wren">import "graphics" for Canvas, ImageData, Color
import "dome" for Window
 
class Game {
static bmpCreate(name, w, h) { ImageData.create(name, w, h) }
 
static bmpFill(name, col) {
var image = ImageData[name]
for (x in 0...image.width) {
for (y in 0...image.height) image.pset(x, y, col)
}
}
 
static bmpPset(name, x, y, col) { ImageData[name].pset(x, y, col) }
 
static bmpPget(name, x, y) { ImageData[name].pget(x, y) }
 
static bmpLine(name, x0, y0, x1, y1, col) {
var dx = (x1 - x0).abs
var dy = (y1 - y0).abs
var sx = (x0 < x1) ? 1 : -1
var sy = (y0 < y1) ? 1 : -1
var err = ((dx > dy ? dx : - dy) / 2).floor
while (true) {
bmpPset(name, x0, y0, col)
if (x0 == x1 && y0 == y1) break
var e2 = err
if (e2 > -dx) {
err = err - dy
x0 = x0 + sx
}
if (e2 < dy) {
err = err + dx
y0 = y0 + sy
}
}
}
 
static init() {
Window.title = "Bresenham's line algorithm"
var size = 200
Window.resize(size, size)
Canvas.resize(size, size)
var name = "bresenham"
var bmp = 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)
}
 
static update() {}
 
static draw(alpha) {}
}</syntaxhighlight>
 
=={{header|XPL0}}==
Bresenham line draw is built-in.
<syntaxhighlight lang="xpl0">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
]</syntaxhighlight>
=={{header|zkl}}==
[[File:Line.zkl.jpg|200px|thumb]]
Algorithm from Wikipedia plus other functions so I can reference this code in other examples.
<syntaxhighlight lang="zkl">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");</syntaxhighlight>
<syntaxhighlight lang="zkl">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) );
}
}
}
}
}</syntaxhighlight>
{{omit from|AWK}}
{{omit from|PARI/GP}}
Anonymous user