Explorar el Código

[rtextures] Adding `ImageDrawLineEx` function (#4097)

* adding `ImageDrawLineEx` function
also review other functions for drawing lines in images

* fix `ImageDrawLineV`
pull/4103/head
Le Juez Victor hace 11 meses
cometido por GitHub
padre
commit
c2df169847
No se encontró ninguna clave conocida en la base de datos para esta firma ID de clave GPG: B5690EEEBB952194
Se han modificado 2 ficheros con 87 adiciones y 72 borrados
  1. +1
    -0
      src/raylib.h
  2. +86
    -72
      src/rtextures.c

+ 1
- 0
src/raylib.h Ver fichero

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

+ 86
- 72
src/rtextures.c Ver fichero

@ -3403,98 +3403,112 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color)
// Draw line within an image
void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
{
// Using Bresenham's algorithm as described in
// Drawing Lines with Pixels - Joshua Scott - March 2012
// https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
// Calculate differences in coordinates
int shortLen = endPosY - startPosY;
int longLen = endPosX - startPosX;
bool yLonger = false;
int changeInX = (endPosX - startPosX);
int absChangeInX = (changeInX < 0)? -changeInX : changeInX;
int changeInY = (endPosY - startPosY);
int absChangeInY = (changeInY < 0)? -changeInY : changeInY;
// Determine if the line is more vertical than horizontal
if (abs(shortLen) > abs(longLen))
{
// Swap the lengths if the line is more vertical
int temp = shortLen;
shortLen = longLen;
longLen = temp;
yLonger = true;
}
int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
//int endV; // Not needed but left for better understanding, check code below
int A, B, P; // See linked paper above, explained down in the main loop
int reversedXY = (absChangeInY < absChangeInX);
// Initialize variables for drawing loop
int endVal = longLen;
int sgnInc = 1;
if (reversedXY)
// Adjust direction increment based on longLen sign
if (longLen < 0)
{
A = 2*absChangeInY;
B = A - 2*absChangeInX;
P = A - absChangeInX;
longLen = -longLen;
sgnInc = -1;
}
if (changeInX > 0)
{
startU = startPosX;
startV = startPosY;
endU = endPosX;
//endV = endPosY;
p">}
else
// Calculate fixed-point increment for shorter length
int decInc = (longLen == 0)? 0 : (shortLen<<16) / longLen;
// Draw the line pixel by pixel
if (yLonger)
{
o">// If line is more vertical, iterate over y-axis
for (int i = 0, j = 0; i != endVal; ss="n">i += sgnInc, j += decInc)
{
startU = endPosX;
startV = endPosY;
endU = startPosX;
//endV = startPosY;
// Since start and end are reversed
changeInX = -changeInX;
changeInY = -changeInY;
// Calculate pixel position and draw it
ImageDrawPixel(dst, startPosX + (j>>16), startPosY + i, color);
}
stepV = (changeInY < 0)? -1 : 1;
ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
}
else
{
A = 2*absChangeInX;
B = A - 2*absChangeInY;
P = A - absChangeInY;
if (changeInY > 0)
{
startU = startPosY;
startV = startPosX;
endU = endPosY;
//endV = endPosX;
}
else
// If line is more horizontal, iterate over x-axis
for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc)
{
startU = endPosY;
startV = endPosX;
endU = startPosY;
//endV = startPosX;
// Since start and end are reversed
changeInX = -changeInX;
changeInY = -changeInY;
// Calculate pixel position and draw it
ImageDrawPixel(dst, startPosX + i, startPosY + (j>>16), color);
}
}
}
// Draw line within an image (Vector version)
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
{
// Round start and end positions to nearest integer coordinates
int x1 = (int)(start.x + 0.5f);
int y1 = (int)(start.y + 0.5f);
int x2 = (int)(end.x + 0.5f);
int y2 = (int)(end.y + 0.5f);
// Draw a vertical line using ImageDrawLine function
ImageDrawLine(dst, x1, y1, x2, y2, color);
}
stepV = (changeInX < 0)? -1 : 1;
// Draw a line defining thickness within an image
void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color)
{
// Round start and end positions to nearest integer coordinates
int x1 = (int)(start.x + 0.5f);
int y1 = (int)(start.y + 0.5f);
int x2 = (int)(end.x + 0.5f);
int y2 = (int)(end.y + 0.5f);
ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below
}
// Calculate differences in x and y coordinates
int dx = x2 - x1;
int dy = y2 - y1;
// Draw the main line between (x1, y1) and (x2, y2)
ImageDrawLine(dst, x1, y1, x2, y2, color);
// We already drew the start point. If we started at startU + 0, the line would be crooked and too short
for (int u = startU + 1, v = startV; u <= endU; u++)
// Determine if the line is more horizontal or vertical
if (dx != 0 && abs(dy/dx) < 1)
{
if (P >= 0)
// Line is more horizontal
// Calculate half the width of the line
int wy = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dx));
// Draw additional lines above and below the main line
for (int i = 1; i <= wy; i++)
{
v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above
P += B; // Remembers that we corrected our path
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color); // Draw above the main line
ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color); // Draw below the main line
}
else P += A; // Remembers how far we are from the direct line
if (reversedXY) ImageDrawPixel(dst, u, v, color);
else ImageDrawPixel(dst, v, u, color);
}
}
else if (dy != 0)
{
// Line is more vertical or perfectly horizontal
// Calculate half the width of the line
int wx = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dy));
// Draw line within an image (Vector version)
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
{
ImageDrawLine(dst, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color);
// Draw additional lines to the left and right of the main line
for (int i = 1; i <= wx; i++)
{
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color); // Draw left of the main line
ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color); // Draw right of the main line
}
}
}
// Draw circle within an image

Cargando…
Cancelar
Guardar