This is just so you understand the logic behind drawing lines, if you understand Bresenham that might be the better option to implement.
A truly perfect pixel line is rather simple, you just need to calculate the ratio like you did in the question, the ratio is the angle of the line. A 45° degree line will have a ratio of 1:1.
Imagine moving a brush, if you have a 1:4 line that means for every 4 pixels you move on the y-axis you have to move one pixel on the x-axis.
Code for that could look like this:
int width = targetX - startX;
int height = targetY - startY;
// At least one of these will be 1
// Depending on wether width or height is larger.
int wRatio = (width / height) || 1 * (width / abs(width));
int hRatio = (height / width) || 1 * (height / abs(height));
int iterations = max(width / wRatio, height / hRatio);
int i = 0;
while(i++ < iterations)
[... draw line segment (filled rectangle) at x,y with width wRatio and height hRatio ...]
x += wRatio;
y += hRatio;
However, sometimes you get don't get around ratios like 1:3.5632, in this case a truly pixel perfect line is not possible. A common approach is alternating between different length line segments and this will also be the case in Bresenham.