Skip to content

Commit c2df169

Browse files
authored
[rtextures] Adding ImageDrawLineEx function (#4097)
* adding `ImageDrawLineEx` function also review other functions for drawing lines in images * fix `ImageDrawLineV`
1 parent c7bda3d commit c2df169

File tree

2 files changed

+87
-72
lines changed

2 files changed

+87
-72
lines changed

src/raylib.h

+1
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,7 @@ RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color);
13731373
RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version)
13741374
RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image
13751375
RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
1376+
RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image
13761377
RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image
13771378
RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version)
13781379
RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image

src/rtextures.c

+86-72
Original file line numberDiff line numberDiff line change
@@ -3403,98 +3403,112 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color)
34033403
// Draw line within an image
34043404
void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
34053405
{
3406-
// Using Bresenham's algorithm as described in
3407-
// Drawing Lines with Pixels - Joshua Scott - March 2012
3408-
// https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
3406+
// Calculate differences in coordinates
3407+
int shortLen = endPosY - startPosY;
3408+
int longLen = endPosX - startPosX;
3409+
bool yLonger = false;
34093410

3410-
int changeInX = (endPosX - startPosX);
3411-
int absChangeInX = (changeInX < 0)? -changeInX : changeInX;
3412-
int changeInY = (endPosY - startPosY);
3413-
int absChangeInY = (changeInY < 0)? -changeInY : changeInY;
3411+
// Determine if the line is more vertical than horizontal
3412+
if (abs(shortLen) > abs(longLen))
3413+
{
3414+
// Swap the lengths if the line is more vertical
3415+
int temp = shortLen;
3416+
shortLen = longLen;
3417+
longLen = temp;
3418+
yLonger = true;
3419+
}
34143420

3415-
int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
3416-
//int endV; // Not needed but left for better understanding, check code below
3417-
int A, B, P; // See linked paper above, explained down in the main loop
3418-
int reversedXY = (absChangeInY < absChangeInX);
3421+
// Initialize variables for drawing loop
3422+
int endVal = longLen;
3423+
int sgnInc = 1;
34193424

3420-
if (reversedXY)
3425+
// Adjust direction increment based on longLen sign
3426+
if (longLen < 0)
34213427
{
3422-
A = 2*absChangeInY;
3423-
B = A - 2*absChangeInX;
3424-
P = A - absChangeInX;
3428+
longLen = -longLen;
3429+
sgnInc = -1;
3430+
}
34253431

3426-
if (changeInX > 0)
3427-
{
3428-
startU = startPosX;
3429-
startV = startPosY;
3430-
endU = endPosX;
3431-
//endV = endPosY;
3432-
}
3433-
else
3432+
// Calculate fixed-point increment for shorter length
3433+
int decInc = (longLen == 0)? 0 : (shortLen<<16) / longLen;
3434+
3435+
// Draw the line pixel by pixel
3436+
if (yLonger)
3437+
{
3438+
// If line is more vertical, iterate over y-axis
3439+
for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc)
34343440
{
3435-
startU = endPosX;
3436-
startV = endPosY;
3437-
endU = startPosX;
3438-
//endV = startPosY;
3439-
3440-
// Since start and end are reversed
3441-
changeInX = -changeInX;
3442-
changeInY = -changeInY;
3441+
// Calculate pixel position and draw it
3442+
ImageDrawPixel(dst, startPosX + (j>>16), startPosY + i, color);
34433443
}
3444-
3445-
stepV = (changeInY < 0)? -1 : 1;
3446-
3447-
ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
34483444
}
34493445
else
34503446
{
3451-
A = 2*absChangeInX;
3452-
B = A - 2*absChangeInY;
3453-
P = A - absChangeInY;
3454-
3455-
if (changeInY > 0)
3456-
{
3457-
startU = startPosY;
3458-
startV = startPosX;
3459-
endU = endPosY;
3460-
//endV = endPosX;
3461-
}
3462-
else
3447+
// If line is more horizontal, iterate over x-axis
3448+
for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc)
34633449
{
3464-
startU = endPosY;
3465-
startV = endPosX;
3466-
endU = startPosY;
3467-
//endV = startPosX;
3468-
3469-
// Since start and end are reversed
3470-
changeInX = -changeInX;
3471-
changeInY = -changeInY;
3450+
// Calculate pixel position and draw it
3451+
ImageDrawPixel(dst, startPosX + i, startPosY + (j>>16), color);
34723452
}
3453+
}
3454+
}
3455+
3456+
// Draw line within an image (Vector version)
3457+
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
3458+
{
3459+
// Round start and end positions to nearest integer coordinates
3460+
int x1 = (int)(start.x + 0.5f);
3461+
int y1 = (int)(start.y + 0.5f);
3462+
int x2 = (int)(end.x + 0.5f);
3463+
int y2 = (int)(end.y + 0.5f);
3464+
3465+
// Draw a vertical line using ImageDrawLine function
3466+
ImageDrawLine(dst, x1, y1, x2, y2, color);
3467+
}
34733468

3474-
stepV = (changeInX < 0)? -1 : 1;
3469+
// Draw a line defining thickness within an image
3470+
void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color)
3471+
{
3472+
// Round start and end positions to nearest integer coordinates
3473+
int x1 = (int)(start.x + 0.5f);
3474+
int y1 = (int)(start.y + 0.5f);
3475+
int x2 = (int)(end.x + 0.5f);
3476+
int y2 = (int)(end.y + 0.5f);
34753477

3476-
ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below
3477-
}
3478+
// Calculate differences in x and y coordinates
3479+
int dx = x2 - x1;
3480+
int dy = y2 - y1;
3481+
3482+
// Draw the main line between (x1, y1) and (x2, y2)
3483+
ImageDrawLine(dst, x1, y1, x2, y2, color);
34783484

3479-
// We already drew the start point. If we started at startU + 0, the line would be crooked and too short
3480-
for (int u = startU + 1, v = startV; u <= endU; u++)
3485+
// Determine if the line is more horizontal or vertical
3486+
if (dx != 0 && abs(dy/dx) < 1)
34813487
{
3482-
if (P >= 0)
3488+
// Line is more horizontal
3489+
// Calculate half the width of the line
3490+
int wy = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dx));
3491+
3492+
// Draw additional lines above and below the main line
3493+
for (int i = 1; i <= wy; i++)
34833494
{
3484-
v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above
3485-
P += B; // Remembers that we corrected our path
3495+
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color); // Draw above the main line
3496+
ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color); // Draw below the main line
34863497
}
3487-
else P += A; // Remembers how far we are from the direct line
3488-
3489-
if (reversedXY) ImageDrawPixel(dst, u, v, color);
3490-
else ImageDrawPixel(dst, v, u, color);
34913498
}
3492-
}
3499+
else if (dy != 0)
3500+
{
3501+
// Line is more vertical or perfectly horizontal
3502+
// Calculate half the width of the line
3503+
int wx = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dy));
34933504

3494-
// Draw line within an image (Vector version)
3495-
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
3496-
{
3497-
ImageDrawLine(dst, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color);
3505+
// Draw additional lines to the left and right of the main line
3506+
for (int i = 1; i <= wx; i++)
3507+
{
3508+
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color); // Draw left of the main line
3509+
ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color); // Draw right of the main line
3510+
}
3511+
}
34983512
}
34993513

35003514
// Draw circle within an image

0 commit comments

Comments
 (0)