Bresenham's line drawing algorithm is well known and quite simple to implement.
While there are more advanced ways to draw anti-ailesed lines, Im interested in writing a function which draws a single pixel width non anti-aliased line, based on floating point coordinates.
This means while the first and last pixels will remain the same, the pixels drawn between them will have a bias based on the sub-pixel position of both end-points.
In principle this shouldn't be all that complicated, since I assume its possible to use the sub-pixel offsets to calculate an initial error
value to use when plotting the line, and all other parts of the algorithm remain the same.
No sub pixel offset:
X###
###X
Assuming the right hand point has a sub-pixel position close to the top, the line could look like this:
With sub pixel offset for example:
X######
X
Is there a tried & true method of drawing a line that takes sub-pixel coordinates into account?
Note:
- This seems like a common operation, I've seen OpenGL drivers take this into account for example - using
GL_LINE
, though from a quick search I didn't find any answers online - maybe used wrong search terms? - At a glance this question looks like it might be a duplicate of:
Precise subpixel line drawing algorithm (rasterization algorithm)
However that is asking about drawing a wide line, this is asking about offsetting a single pixel line. - If there isn't some standard method, I'll try write this up to post as an answer.
Let's assume you want to draw a line from
P1 = (x1, y1)
toP2 = (x2, y2)
where all the numbers are floating point pixel coordinates.Calculate the true pixel coordinates of
P1
andP2
and paint them:P* = (round(x), round(y))
.If
abs(x1* - x2*) <= 1 && abs(y1* - y2*) <= 1
then you are finished.Decide whether it is a horizontal (true) or a vertical line (false):
abs(x1 - x2) >= abs(y1 - y2)
.If it is a horizontal line and
x1 > x2
or if it is a vertical line andy1 > y2
: swapP1
withP2
(and alsoP1*
withP2*
).If it is a horizontal line you can get the y-coordinates for all the x-coordinates between
x1*
andx2*
with the following formula:If you have a vertical line you can get the x-coordinates for all the y-coordinates between
y1*
andy2*
with this formula:Here is a demo you can play around with, you can try different points on line 12.