Académique Documents
Professionnel Documents
Culture Documents
Contents
[hide]
1 Ada
2 ALGOL 68
3 Assembly
4 AutoHotkey
5 AutoIt
6 BASIC
7 BBC BASIC
8 Batch File
9C
10 C#
11 C++
12 Clojure
13 CoffeeScript
14 Common Lisp
15 D
16 Delphi
17 Elm
18 E
19 Erlang
20 ERRE
21 Euphoria
22 F#
23 FBSL
24 Factor
25 Forth
26 Fortran
27 FreeBASIC
28 Go
29 Haskell
30 J
31 Java
32 JavaScript
33 Julia
34 Korn Shell
35 Kotlin
36 Maple
37 Mathematica / Wolfram Language
38 MATLAB
39 MAXScript
40 Metal
41 Nim
42 OCaml
43 Pascal
44 Perl
45 Perl 6
46 Phix
47 PicoLisp
48 PL/I
o 48.1 version 1
o 48.2 version 2
49 Prolog
50 PureBasic
51 Python
o 51.1 Not relying on floats
52 Racket
53 RapidQ
54 REXX
o 54.1 version 1
o 54.2 version 2
55 Ring
56 Ruby
57 Scala
58 Sidef
59 Tcl
60 TI-89 BASIC
61 Vedit macro language
62 Wart
63 XPL0
64 zkl
Ada [edit]
sample output
H
H H
H H
H HH
H H
H H
H H
H H
H H
H H
H H
H H
H H
H H
H H
H
ALGOL 68 [edit]
line OF class image := (REF IMAGE picture, POINT start, stop, PIXEL
color)VOID:
BEGIN
REAL dx = ABS (x OF stop - x OF start),
dy = ABS (y OF stop - y OF start);
REAL err;
POINT here := start,
step := (1, 1);
IF x OF start > x OF stop THEN
x OF step := -1
FI;
IF y OF start > y OF stop THEN
y OF step := -1
FI;
IF dx > dy THEN
err := dx / 2;
WHILE x OF here /= x OF stop DO
picture[x OF here, y OF here] := color;
err -:= dy;
IF err < 0 THEN
y OF here +:= y OF step;
err +:= dx
FI;
x OF here +:= x OF step
OD
ELSE
err := dy / 2;
WHILE y OF here /= y OF stop DO
picture[x OF here, y OF here] := color;
err -:= dx;
IF err < 0 THEN
x OF here +:= x OF step;
err +:= dy
FI;
y OF here +:= y OF step
OD
FI;
picture[x OF here, y OF here] := color # ensure dots to be drawn
#
END # line #;
SKIP
File: test/Bitmap/Bresenhams_line_algorithm.a68
#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
Output:
ffffffffffffffffffffffffffffffffffffffffff000000fffffffffffffffffff
fffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffff000000ffffff000000fffffffffffff
fffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffff000000ffffffffffffffffff000000fffffff
fffffffffffffffffffffffffffff
ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff0000000
00000ffffffffffffffffffffffff
ffffffffffffffffff000000fffffffffffffffffffffffffffffffffffffffffff
fffff000000ffffffffffffffffff
ffffffffffff000000fffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffff000000ffffffffffff
ffffff000000fffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffff000000ffffff
000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffffffff000000
ffffff000000fffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffff000000ffffff
ffffffffffff000000fffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffff000000ffffffffffff
ffffffffffffffffff000000fffffffffffffffffffffffffffffffffffffffffff
fffff000000ffffffffffffffffff
ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffffffffff0
00000ffffffffffffffffffffffff
ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff000000f
fffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffff000000ffffffffffffffffff000000fffffff
fffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffff000000ffffff000000fffffffffffff
fffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffff000000fffffffffffffffffff
fffffffffffffffffffffffffffff
Assembly [edit]
16 bit Intel 8086\80486 Assembly for dos, see x86 assembly language. To run this
code you will need to use Dos emulator.
.486
IDEAL
;---------------------------------------------
; case: DeltaY is bigger than DeltaX
; input: p1X p1Y,
; p2X p2Y,
; Color -> variable
; output: line on the screen
;---------------------------------------------
Macro DrawLine2DDY p1X, p1Y, p2X, p2Y
local l1, lp, nxt
mov dx, 1
mov ax, [p1X]
cmp ax, [p2X]
jbe l1
neg dx ; turn delta to -1
l1:
mov ax, [p2Y]
shr ax, 1 ; div by 2
mov [TempW], ax
mov ax, [p1X]
mov [pointX], ax
mov ax, [p1Y]
mov [pointY], ax
mov bx, [p2Y]
sub bx, [p1Y]
absolute bx
mov cx, [p2X]
sub cx, [p1X]
absolute cx
mov ax, [p2Y]
lp:
pusha
call PIXEL
popa
inc [pointY]
cmp [TempW], 0
jge nxt
add [TempW], bx ; bx = (p2Y - p1Y) = deltay
add [pointX], dx ; dx = delta
nxt:
sub [TempW], cx ; cx = abs(p2X - p1X) = daltax
cmp [pointY], ax ; ax = p2Y
jne lp
call PIXEL
ENDM DrawLine2DDY
;---------------------------------------------
; case: DeltaX is bigger than DeltaY
; input: p1X p1Y,
; p2X p2Y,
; Color -> variable
; output: line on the screen
;---------------------------------------------
Macro DrawLine2DDX p1X, p1Y, p2X, p2Y
local l1, lp, nxt
mov dx, 1
mov ax, [p1Y]
cmp ax, [p2Y]
jbe l1
neg dx ; turn delta to -1
l1:
mov ax, [p2X]
shr ax, 1 ; div by 2
mov [TempW], ax
mov ax, [p1X]
mov [pointX], ax
mov ax, [p1Y]
mov [pointY], ax
mov bx, [p2X]
sub bx, [p1X]
absolute bx
mov cx, [p2Y]
sub cx, [p1Y]
absolute cx
mov ax, [p2X]
lp:
pusha
call PIXEL
popa
inc [pointX]
cmp [TempW], 0
jge nxt
add [TempW], bx ; bx = abs(p2X - p1X) = deltax
add [pointY], dx ; dx = delta
nxt:
sub [TempW], cx ; cx = abs(p2Y - p1Y) = deltay
cmp [pointX], ax ; ax = p2X
jne lp
call PIXEL
ENDM DrawLine2DDX
Macro absolute a
local l1
cmp a, 0
jge l1
neg a
l1:
Endm
MODEL small
STACK 256
DATASEG
TempW dw ?
pointX dw ?
pointY dw ?
point1X dw ?
point1Y dw ?
point2X dw ?
point2Y dw ?
Color db ?
CODESEG
start:
mov ax, @data
mov ds, ax
mov [Color], 61
mov [point1X], 300
mov [point2X], 6
mov [point1Y], 122
mov [point2Y], 88
call DrawLine2D
AutoHotkey [edit]
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
AutoIt [edit]
BASIC [edit]
Width% = 200
Height% = 200
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
Batch File [edit]
@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
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"
)
)
set stepy=1
set stepx=1
set /a dx=x2-x1
set /a dy=y2-y1
C [edit]
Instead of swaps in the initialisation use error calculation for both directions x and y
simultaneously:
for(;;){
setPixel(x0,y0);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
C# [edit]
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, 7
5, 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;
}
}
C++ [edit]
void Line( const float x1, const float y1, const float x2, const fl
oat 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);
}
error -= dy;
if(error < 0)
{
y += ystep;
error += dx;
}
}
}
Clojure [edit]
(defn draw-line
"Draw a line from x1,y1 to x2,y2 using Bresenham's, to a java Buf
feredImage 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)]
CoffeeScript [edit]
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
D [edit]
module bitmap_bresenhams_line_algorithm;
error += dy2;
x1 += ix;
img[x1, y1] = color;
}
} else {
int error = dx2 - (dy2 / 2);
while (y1 != y2) {
if (error >= 0 && (error || (iy > 0))) {
error -= dy2;
x1 += ix;
}
error += dx2;
y1 += iy;
img[x1, y1] = color;
}
}
}
version (bitmap_bresenhams_line_algorithm_main) {
void main() {
auto img = new Image!RGB(25, 22);
img.drawLine(5, 5, 15, 20, RGB.white);
img.drawLine(3, 20, 10, 12, RGB.white);
img.textualShow();
}
}
Output:
#########################
#########################
#########################
#########################
#########################
#####.###################
######.##################
######.##################
#######.#################
########.################
########.################
#########.###############
##########.##############
#########..##############
########.##.#############
#######.####.############
######.#####.############
######.######.###########
#####.########.##########
####.#########.##########
###.###########.#########
#########################
Delphi [edit]
Elm [edit]
-- Brensenham Line Algorithm
error =
(if dx > dy then dx else -dy) / 2
statics =
BresenhamStatics q sx sy dx dy
in
bresenhamLineLoop statics error p []
(dErrY, y) =
if error < dy then (dx, sy + p.y)
else (0, p.y)
E [edit]
Translation of: C
def drawLine(image, var x0, var y0, var x1, var y1, color) {
def steep := (y1 - y0).abs() > (x1 - x0).abs()
if (steep) {
swap(&x0, &y0)
swap(&x1, &y1)
}
if (x0 > x1) {
swap(&x0, &x1)
swap(&y0, &y1)
}
def deltax := x1 - x0
def deltay := (y1 - y0).abs()
def ystep := if (y0 < y1) { 1 } else { -1 }
var error := deltax // 2
var y := y0
for x in x0..x1 {
if (steep) { image[y, x] := color } else { image[x, y] := c
olor }
error -= deltay
if (error < 0) {
y += ystep
error += deltax
}
}
}
def i := makeImage(5, 20)
drawLine(i, 1, 1, 3, 18, makeColor.fromFloat(0,1,1))
i.writePPM(<import:java.io.makeFileOutputStream>(<file:~/Desktop/Br
esenham.ppm>))
Erlang [edit]
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}, {D
x, Dy}, Dy*2-Dx, [])
end,
lists:reverse(Path).
OR
ERRE [edit]
PROGRAM BRESENHAM
!$INCLUDE="PC.LIB"
PROCEDURE BRESENHAM
! === Draw a line using graphic coordinates
! Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
dx=ABS(x2-x1) sx=-1
IF x1<x2 THEN sx=1
dy=ABS(y2-y1) sy=-1
IF y1<y2 THEN sy=1
er=-dy
IF dx>dy THEN er=dx
er=INT(er/2)
LOOP
PSET(x1,y1,1)
EXIT IF x1=x2 AND y1=y2
e2=er
IF e2>-dx THEN er=er-dy x1=x1+sx
IF e2<dy THEN er=er+dx y1=y1+sy
END LOOP
END PROCEDURE
BEGIN
SCREEN(2)
INPUT(x1,y1,x2,y2)
BRESENHAM
GET(A$)
SCREEN(0)
END PROGRAM
Euphoria [edit]
Translation of: C
include std/console.e
include std/graphics.e
include std/math.e
if x0 < x1 then
stepX = 1
else
stepX = -1
end if
if y0 < y1 then
stepY = 1
else
stepY = -1
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
puts(1,"\n\n")
any_key()
--/*
--output was edited to replace the color's hex digits for clearer o
utput graphics.
--to output all the hex digits, use printf(1,"%06x", screenData[j][
i])
--to output 'shortened' hex digits, use :
--printf(1, "%x", ( abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) - 1
) )
--and
--printf(1,"%x", abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) )
--
--,respectively in the last if check.
--*/
Output:
.......#........
......#.#.......
.....#...#......
....#..#..##....
...#..#.#...#...
..#..#...#...#..
.#..#.###.#...#.
#..#...#...#...#
.#..#.###.#...#.
..#..#...#...#..
...#..#.#...#...
....#..#...#....
....#.....#.....
.....#...#......
......#.#.......
.......#........
F# [edit]
The following program tests the above bresenham function by drawing 100 lines into
an image and visualizing the result using
Library: Windows Presentation Foundation
:
open System.Windows
open System.Windows.Media.Imaging
[<System.STAThread>]
do
let rand = System.Random()
let n = 256
let pixel = Array.create (n*n) 0uy
let rand = System.Random().Next
for _ in 1..100 do
bresenham (fun x y -> pixel.[x+y*n] <- 255uy) (rand n, rand n)
(rand n, rand n)
let image = Controls.Image(Stretch=Media.Stretch.Uniform)
let format = Media.PixelFormats.Gray8
image.Source <-
BitmapSource.Create(n, n, 1.0, 1.0, format, null, pixel, n)
Window(Content=image, Title="Bresenham's line algorithm")
|> (Application()).Run |> ignore
FBSL [edit]
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:
SUB Rhombus()
Bresenham(50, 100, 100, 190)(100, 190, 150, 100)(150, 100, 100, 1
0)(100, 10, 50, 100)
Output:
Factor [edit]
Forth [edit]
Fortran [edit]
module RCImagePrimitive
use RCImageBasic
implicit none
type point
integer :: x, y
end type point
private :: swapcoord
contains
t = p2
p2 = p1
p1 = t
end subroutine swapcoord
rfrom = from
rto = to
steep = (abs(rto%y - rfrom%y) > abs(rto%x - rfrom%x))
if ( steep ) then
call swapcoord(rfrom%x, rfrom%y)
call swapcoord(rto%x, rto%y)
end if
if ( rfrom%x > rto%x ) then
call swapcoord(rfrom%x, rto%x)
call swapcoord(rfrom%y, rto%y)
end if
dx = rto%x - rfrom%x
dy = abs(rto%y - rfrom%y)
error = dx / 2
y = rfrom%y
do x = rfrom%x, rto%x
if ( steep ) then
call put_pixel(img, y, x, color)
else
call put_pixel(img, x, y, color)
end if
error = error - dy
if ( error < 0 ) then
y = y + ystep
error = error + dx
end if
end do
Usage example:
program BasicImageTests
use RCImageBasic
use RCImageIO
use RCImagePrimitive
implicit none
type(rgbimage) :: animage
integer :: x, y
call free_img(animage)
FreeBASIC [edit]
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
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
Go [edit]
package raster
for {
b.SetPx(x0, y0, p)
if x0 == x1 && y0 == y1 {
break
}
e2 := 2 * err
if e2 > -dy {
err -= dy
x0 += sx
}
if e2 < dx {
err += dx
y0 += sy
}
}
}
A demonstration program:
package main
import (
"raster"
"fmt"
)
func main() {
b := raster.NewBitmap(400, 300)
b.FillRgb(0xdfefff)
blue := raster.Rgb(0x8fcfff)
b.LineRgb(7, 12, 307, 122, blue)
b.LineRgb(177, 12, 127, 222, blue)
err := b.WritePpmFile("bresenham.ppm")
if err != nil {
fmt.Println(err)
}
}
Haskell [edit]
import Bitmap
import Control.Monad
import Control.Monad.ST
import qualified Data.STRef
var = Data.STRef.newSTRef
get = Data.STRef.readSTRef
mutate = Data.STRef.modifySTRef
line :: Color c => Image s c -> Pixel -> Pixel -> c -> ST s ()
line i (Pixel (xa, ya)) (Pixel (xb, yb)) c = do
yV <- var y1
errorV <- var $ deltax `div` 2
forM_ [x1 .. x2] (\x -> do
y <- get yV
setPix i (Pixel $ if steep then (y, x) else (x, y)) c
mutate errorV $ subtract deltay
error <- get errorV
when (error < 0) (do
mutate yV (+ ystep)
mutate errorV (+ deltax)))
where steep = abs (yb - ya) > abs (xb - xa)
(xa', ya', xb', yb') = if steep
then (ya, xa, yb, xb)
else (xa, ya, xb, yb)
(x1, y1, x2, y2) = if xa' > xb'
then (xb', yb', xa', ya')
else (xa', ya', xb', yb')
deltax = x2 - x1
deltay = abs $ y2 - y1
ystep = if y1 < y2 then 1 else -1
J[edit]
Solution:
Using definitions from Basic bitmap storage.
Example Usage:
Java [edit]
import java.awt.*;
import javax.swing.*;
public BresenhamPanel() {
int w = 600;
int h = 500;
centerX = w / 2;
centerY = h / 2;
setPreferredSize(new Dimension(w, h));
setBackground(Color.white);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
private void drawLine(Graphics g, int x1, int y1, int x2, int y
2) {
// delta of exact value and rounded value of the dependant
variable
int d = 0;
int dy2 = (dy << 1); // slope scaling factors to avoid floa
ting
int dx2 = (dx << 1); // point
int ix = x1 < x2 ? 1 : -1; // increment direction
int iy = y1 < y2 ? 1 : -1;
JavaScript [edit]
Instead of swaps in the initialisation use error calculation for both directions x and y
simultaneously:
while (true) {
setPixel(x0,y0);
if (x0 === x1 && y0 === y1) break;
var e2 = err;
if (e2 > -dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
Julia [edit]
function line(img, x0::Int, y0::Int, x1::Int, y1::Int, col)
dx = int(abs(x1-x0))
dy = int(abs(y1-y0))
sx = x0<x1 ? 1 : -1
sy = y0<y1 ? 1 : -1;
while true
@inbounds img[x0,y0]=col
if (x0==x1 && y0==y1); break; end
e2 = err;
if e2 > -dx
err -= dy
x0 += sx
end
if e2 < dy
err += dx
y0 += sy
end
end
end
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 /bin/true
do
echo $x0 $y0
(( x0 == x1 && y0 == y1 )) && return
((e2 = err))
(( e2 > -dx)) && { ((err -= dy )); (( x0 += sx )) }
(( e2 < dy)) && { ((err += dx )); (( y0 += sy )) }
done
}
line 0 0 3 4
0 0
1 1
1 2
2 3
3 4
Kotlin [edit]
// version 1.1.1
import java.awt.*
import javax.swing.*
init {
preferredSize = Dimension(w, h)
background = Color.blue
}
private fun drawLine(g: Graphics, x1: Int, y1: Int, x2: Int, y2
: Int) {
var d = 0
val dy = Math.abs(y2 - y1)
val dx = Math.abs(x2 - x1)
val dy2 = dy shl 1
val dx2 = dx shl 1
val ix = if (x1 < x2) 1 else -1
val iy = if (y1 < y2) 1 else -1
var xx = x1
var yy = y1
Maple [edit]
SegmentBresenham := proc (img, x0, y0, x1, y1)
local deltax, deltay, x, y, ystep, steep, err, img2, x02, y02,
x12, y12;
x02, x12, y02, y12 := y0, y1, x0, x1;
steep := abs(x12 - x02) < abs(y12 - y02);
img2 := copy(img);
if steep then
x02, y02 := y02, x02;
x12, y12 := y12, x12;
end if;
if x12 < x02 then
x02, x12 := x12, x02;
y02, y12 := y12, y02;
end if;
deltax := x12 - x02;
deltay := abs(y12 - y02);
err := deltax / 2;
y := y02;
if y02 < y12 then
ystep := 1
else
ystep := -1
end if;
for x from x02 to x12 do
if steep then
img2[y, x] := 0
else
img2[x, y] := 0
end if;
err := err - deltay;
if err < 0 then
y := y + ystep;
err := err + deltax
end if;
end do;
return img2;
end proc:
MATLAB [edit]
Note: Store this function in a file named "bresenhamLine.m" in the @Bitmap folder for
the Bitmap class defined here.
MATLAB sample usage output.
function bresenhamLine(screen,startPoint,endPoint,color)
err = dx - dy;
pixel = startPoint;
while(true)
screen.setPixel(pixel,color); %setPixel(x0,y0)
if( pixel == endPoint )
break;
end
e2 = 2*err;
if( e2 < dx )
err = err + dx;
pixel(2) = pixel(2) + sy;
end
end
Sample Usage:
MAXScript [edit]
if steep then
(
swap start.x start.y
swap end.x end.y
)
Metal [edit]
int e2 = err;
Nim [edit]
import math
var
p = p
q = q
err = (if dx > dy: dx else: -dy) div 2
e2 = 0
while true:
img[p] = Black
if p == q:
break
e2 = err
if e2 > -dx:
err -= dy
p.x += sx
if e2 < dy:
err += dx
p.y += sy
OCaml [edit]
let plot =
if steep
then (fun x y -> put_pixel img color y x)
else (fun x y -> put_pixel img color x y)
in
let delta_x = x1 - x0
and delta_y = abs(y1 - y0) in
let error = -delta_x / 2
and y_step =
if y0 < y1 then 1 else -1
in
let rec loop x y error =
plot x y;
if x <= x1 then
let error = error + delta_y in
let y, error =
if error > 0
then (y + y_step), (error - delta_x)
else y, error
in
loop (succ x) y error
in
loop x0 y0 error
;;
Pascal [edit]
Delphi
Perl [edit]
Library: Imlib2
#! /usr/bin/perl
use strict;
use Image::Imlib2;
sub my_draw_line
{
my ( $img, $x0, $y0, $x1, $y1) = @_;
# test
my $img = Image::Imlib2->new(160, 160);
$img->set_color(255, 255, 255, 255); # white
$img->fill_rectangle(0,0,160,160);
$img->set_color(0,0,0,255); # 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");
$img->save("test1.png");
exit 0;
Images test0.png and test1.png look different since Imlib2 draw lines with
antialiasing.
Perl 6 [edit]
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;
}
}
}
Phix [edit]
Modified copy of Euphoria, with a bigger bitmap and a simpler pattern. Requires
new_image() from Bitmap, write_ppm() from Write_a_PPM_file. Included as
demo\rosetta\Bresenham_line.exw, results may be verified with
demo\rosetta\viewppm.exw
PicoLisp [edit]
(let Img (make (do 90 (link (need 120 0)))) # Create image 1
20 x 90
(brez Img 10 10 100 30) # Draw five line
s
(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 bitma
p file
(prinl "P1")
(prinl 120 " " 90)
(mapc prinl Img) ) )
PL/I [edit]
version 1[edit]
This example is incorrect. Please fix the code and remove this message.
Details: The sample output does not start at -1/-3!?! Pls show the complete program producing th
end draw_line;
..........|..........
..........|..........
..........|..........
..........|..........
..........|..........
..........|..........
..........|.........*
..........|.......**.
..........|.....**...
..........|...**.....
----------+-**-------
..........**.........
........**|..........
.......*..|..........
..........|..........
..........|..........
..........|..........
..........|..........
..........|..........
..........|..........
..........|..........
version 2[edit]
*process source xref or(!);
brbn:Proc Options(main);
/*****************************************************************
****
* 21.05.2014 Walter Pachl
* Implementing the pseudo code of
* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
* under 'Simplification' (see also REXX version 2)
******************************************************************
***/
grid.=
dcl image(-2:7,-4:11) char(1);
image='.';
image(*,0)='-';
image(0,*)='|';
image(0,0)='+';
call draw_line(-1,-3,6,10);
Dcl (i,j) Bin Fixed(31);
Do j=11 To -4 By -1;
Put Edit(j,' ')(Skip,f(2),a);
Do i=-2 To 7;
Put Edit(image(i,j))(a);
End;
End;
Put Edit(' 2101234567')(Skip,a);
dx = abs(x1-x0);
dy = abs(y1-y0);
if x0 < x1 then sx = 1;
else sx = -1;
if y0 < y1 then sy = 1;
else sy = -1;
err = dx-dy;
Do Until(x0=x1&y0=y1);
image(x0,y0)='X';
e2=err*2;
if e2>-dy then do;
err=err-dy;
x0=x0+sx;
End;
if e2<dx then do;
err=err+dx;
y0=y0+sy;
End;
End;
image(x0,y0)='X';
end;
end;
output
11 ..|.......
10 ..|.....X.
9 ..|....X..
8 ..|....X..
7 ..|...X...
6 ..|...X...
5 ..|..X....
4 ..|..X....
3 ..|.X.....
2 ..|.X.....
1 ..|X......
0 --+X------
-1 ..X.......
-2 ..X.......
-3 .X|.......
-4 ..|.......
2101234567
Prolog [edit]
use_module(library(pce)).
lindraw(X1,Y1,X2,Y2):-
new(Win,window("Line")),
new(Pix,pixmap(@nil,black,white,X2+30,Y2+30)),
send(Win,size,size(400,400)),
draw_line(Pix,X1,Y1,X2,Y2),
new(Bmp,bitmap(Pix)),
send(Win,display,Bmp,point(0,0)),
send(Win,open).
draw_recursive_line(_Pict,X,X,_DX,_DY,Y,Y,_D,_Sx,_Sy).%Don't iterat
e if X and X2 are the same number
draw_recursive_line(Pict,X,X2,DX,DY,Y,Y2,C,Sx,Sy):-
( C>0->%If the difference is greater than one, add Y one to Y
.
Y1 is Y+Sy,
send(Pict,pixel(X,Y1,colour(black))),
C2 is C+(2*DY-2*DX);
Y1 is Y,
send(Pict,pixel(X,Y,colour(black))),
C2 is C+(2*DY)),
X0 is X+Sx,%The next iteration
draw_recursive_line(Pict,X0,X2,DX,DY,Y1,Y2,C2,Sx,Sy).
isneg(X,O):-
( X<0->
O is -1;
( X\==0->
O is 1;
O is 0)).
draw_line(Pict,X1,Y1,X2,Y2):-
DY is abs(Y2-Y1),
DX is abs(X2-X1),
isneg(DX,Sx),
isneg(DY,Sy),
D = 2*DY-DX,%The slope of the line
draw_recursive_line(Pict,X1,X2,DX,DY,Y1,Y2,D,Sx,Sy).
PureBasic [edit]
#Window1 = 0
#Image1 = 0
#ImgGadget = 0
#width = 300
#height = 300
Define.i Event
Define.f Angle
StopDrawing()
SetGadgetState(#ImgGadget, ImageID(#Image1))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
Python [edit]
bitmap = Bitmap(17,17)
for points in ((1,8,8,16),(8,16,16,8),(16,8,8,1),(8,1,1,8)):
bitmap.line(*points)
bitmap.chardisplay()
'''
The origin, 0,0; is the lower left, with x increasing to the right,
and Y increasing upwards.
Bitmap.line = line
Racket [edit]
#lang racket
(require racket/draw)
RapidQ [edit]
Use this routine together with the code from Basic bitmap storage to create a full
application.
END SUB
Example usage:
SUB PaintCanvas
draw_line 200, 10, 100, 200, &H00ff00
draw_line 100, 200, 200, 400, &H00ff00
draw_line 200, 400, 300, 200, &H00ff00
draw_line 300, 200, 200, 10, &H00ff00
END SUB
REXX [edit]
version 1[edit]
This REXX version has automatic scaling (for displaying the plot), includes a
border, accepts lines segments from the
command line, and it also handles multiple line segments.
···│····················
···│····················
···│·······Θ············
···│······Θ·Θ···········
···│·····Θ···Θ··········
···│····Θ·····Θ·········
···│···Θ·······Θ········
···│···Θ········Θ·······
···│··Θ··········Θ······
···│·Θ············Θ·····
···│Θ··············Θ····
···│·Θ············Θ·····
···│··Θ··········Θ······
···│···Θ·······ΘΘ·······
···│····Θ·····Θ·········
···│·····Θ···Θ··········
···│······Θ·Θ···········
···│·······Θ············
───┼────────────────────
···│····················
version 2[edit]
/* 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
output
11 ..|.......
10 ..|.....X.
9 ..|....X..
8 ..|....X..
7 ..|...X...
6 ..|...X...
5 ..|..X....
4 ..|..X....
3 ..|.X.....
2 ..|.X.....
1 ..|X......
0 --+X------
-1 ..X.......
-2 ..X.......
-3 .X|.......
-4 ..|.......
2101234567
Ring [edit]
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)
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 o
k
else
y1 += sy e -= dx if e < 0 e += dy x1 += sx ok
ok
end
next
endpaint()
}
label1 { setpicture(p1) show() }
Output : Bitmap/Bresenham's algorithm
Ruby [edit]
class Pixmap
if steep
x1, y1 = y1, x1
x2, y2 = y2, x2
end
if x1 > x2
x1, x2 = x2, x1
y1, y2 = y2, y1
end
deltax = x2 - x1
deltay = (y2 - y1).abs
error = deltax / 2
ystep = y1 < y2 ? 1 : -1
y = y1
x1.upto(x2) do |x|
pixel = steep ? [y,x] : [x,y]
self[*pixel] = colour
error -= deltay
if error < 0
y += ystep
error += deltax
end
end
end
end
Scala [edit]
Sidef [edit]
if (steep) {
(y0, x0) = (x0, y0)
(y1, x1) = (x1, y1)
}
if (x0 > x1) {
(x1, x0) = (x0, x1)
(y1, y0) = (y0, y1)
}
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')
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");
img.save("test1.png")
Tcl [edit]
Library: Tk
ref Basic bitmap storage#Tcl
Note: This example does not use a user-defined image type, since that would be
particularly impractical, but rather draws on the calculator's graph screen, which has
essentially the same operations as an implementation of Basic bitmap storage would,
except for being black-and-white.
Translation of: E
: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
Wart [edit]
XPL0 [edit]
zkl [edit]
Algorithm from Wikipedia plus other functions so I can reference this code in other
examples.
ppm:=PPM(200,200,0xFF|FF|FF);
ppm.line(50,100, 100,190, 0);
ppm.line(100,190, 150,100, 0);
ppm.line(150,100, 100,10, 0);
ppm.line(100,10, 50,100, 0);
ppm.writeJPGFile("line.jpg");
class PPM{ // (0,0) is logically bottom left
fcn init(width,height,rgb=0){
sz:=width*height;
var [const]
data=Data(sz*3).fill(rgb.toBigEndian(3).toData()), // ini
tialize 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.r
ead(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 get
s 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) )
;
}
}
}
}
}