[Back to the 30 Days of Programming Overview Page]
Bresenham's Line Algorithm on TachibanaSite (Python 2 + Pillow)
Source Code
(bresenham.markdown.template)
<%
# vim: set filetype=python :
import base64
import io
import math
from PIL import Image, ImageDraw
width = 128
height = 72
im = Image.new('1', (width, height), 0)
debug = ImageDraw.Draw(im)
# Get parameters
try:
x1, y1, x2, y2 = [int(_GET[key]) for key in ['x1', 'y1', 'x2', 'y2']]
for x in (x1, x2):
if x < 0 or x >= width:
raise ValueError
end
end
for y in (y1, y2):
if y < 0 or y >= height:
raise ValueError
end
end
except (ValueError, KeyError):
debug.text((2, 0), 'INVALID', fill=1)
x1 = y1 = x2 = y2 = 0
end
# Go from a to b inclusive with tep one regardless of direction
def xrange_inclusive(a, b):
if a > b:
return xrange(a, b - 1, -1)
else:
return xrange(a, b + 1)
end
end
# Bresenham's line algorithm
dx = x2 - x1
dy = y2 - y1
high_slope = (abs(dy) > abs(dx))
#debug.text((2, 0), '{},{}'.format(dx, dy), fill=1)
if high_slope:
x1, y1 = y1, x1
x2, y2 = y2, x2
dx, dy = dy, dx
end
derr = abs(float(dy) / dx)
error = 0.0
y = y1
for x in xrange_inclusive(x1, x2):
im.putpixel((y, x) if high_slope else (x, y), 1)
error += derr
while error >= 0.5:
y += int(math.copysign(1, dy))
error -= 1
end
end
# Output to the page
buffer = io.BytesIO()
(Image.eval(im, lambda p: 1 - p)
.resize((width*10, height*10))
.save(buffer, 'PNG'))
data = base64.b64encode(buffer.getvalue())
%>
<p style="margin: 0px;">
<img style="width: 100%;"
src="data:image/png;base64,{{!data}}"
/>
</p>