## Antialiased line

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
lester
Filthy Rich wx Solver Posts: 211
Joined: Sat Sep 02, 2006 7:24 pm
Location: Ukraine

### Antialiased line

wxWidgets implementation of Wu's algorithm

Code: Select all

``````/**********************************************************************************************/
wxColour GetColorAverage( wxColour color1, wxColour color2, float weight)
{
unsigned char r, g, b;

r = (unsigned char)( 1.0 * color1.Red() * weight + 1.0 * color2.Red() * ( 1 - weight) );
g = (unsigned char)( 1.0 * color1.Green() * weight + 1.0 * color2.Green() * ( 1 - weight) );
b = (unsigned char)(1.0 * color1.Blue() * weight + 1.0 * color2.Blue() * ( 1 - weight) );

return wxColour(r, g, b);
}

/**********************************************************************************************/
void DrawWuLine( wxDC *pDC, short X0, short Y0, short X1, short Y1 )
{
wxASSERT( pDC );

if( !pDC )
return;

wxColour cl = pDC->GetPen().GetColour();
wxColour clb = pDC->GetBrush().GetColour();
short DeltaX, DeltaY, Temp, XDir;

/* Make sure the line runs top to bottom */
if (Y0 > Y1) {
Temp = Y0; Y0 = Y1; Y1 = Temp;
Temp = X0; X0 = X1; X1 = Temp;
}
/* Draw the initial pixel, which is always exactly intersected by
the line and so needs no weighting */
pDC->SetPen( cl );
pDC->DrawPoint( X0, Y0 );

if ((DeltaX = X1 - X0) >= 0) {
XDir = 1;
} else {
XDir = -1;
DeltaX = -DeltaX; /* make DeltaX positive */
}
/* Special-case horizontal, vertical, and diagonal lines, which
require no weighting because they go right through the center of
every pixel */
if ((DeltaY = Y1 - Y0) == 0) {
/* Horizontal line */
while (DeltaX-- != 0) {
X0 += XDir;
pDC->DrawPoint( X0, Y0 );
}
return;
}
if (DeltaX == 0) {
/* Vertical line */
do {
Y0++;
pDC->DrawPoint( X0, Y0 );
} while (--DeltaY != 0);
return;
}
if (DeltaX == DeltaY) {
/* Diagonal line */
do {
X0 += XDir;
Y0++;
pDC->DrawPoint( X0, Y0 );
} while (--DeltaY != 0);
return;
}
/* Line is not horizontal, diagonal, or vertical */
ErrorAcc = 0;  /* initialize the line error accumulator to 0 */
/* # of bits by which to shift ErrorAcc to get intensity level */
IntensityShift = 8;
/* Mask used to flip all bits in an intensity weighting, producing the
result (1 - intensity weighting) */
/* Is this an X-major or Y-major line? */
if (DeltaY > DeltaX) {
/* Y-major line; calculate 16-bit fixed-point fractional part of a
pixel that X advances each time Y advances 1 pixel, truncating the
result so that we won't overrun the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
/* Draw all pixels other than the first and last */
while (--DeltaY) {
ErrorAccTemp = ErrorAcc;   /* remember current accumulated error */
ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the X coord */
X0 += XDir;
}
Y0++; /* Y-major, so always advance Y */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;

wxColour cl2 = GetColorAverage( clb, cl, 1. * Weighting / 255 );
pDC->SetPen( cl2 );
pDC->DrawPoint( X0, Y0 );
cl2 = GetColorAverage( clb, cl, 1. * ( Weighting ^ WeightingComplementMask ) / 255 );
pDC->SetPen( cl2 );
pDC->DrawPoint( X0 + XDir, Y0 );
}
/* Draw the final pixel, which is
always exactly intersected by the line
and so needs no weighting */
pDC->SetPen( cl );
pDC->DrawPoint( X1, Y1 );
return;
}
/* It's an X-major line; calculate 16-bit fixed-point fractional part of a
pixel that Y advances each time X advances 1 pixel, truncating the
result to avoid overrunning the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
/* Draw all pixels other than the first and last */
while (--DeltaX) {
ErrorAccTemp = ErrorAcc;   /* remember currrent accumulated error */
ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the Y coord */
Y0++;
}
X0 += XDir; /* X-major, so always advance X */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
wxColour cl2 = GetColorAverage( clb, cl, 1. * Weighting / 255 );
pDC->SetPen( cl2 );
pDC->DrawPoint( X0, Y0 );
cl2 = GetColorAverage( clb, cl, 1. * ( Weighting ^ WeightingComplementMask ) / 255 );
pDC->SetPen( cl2 );
pDC->DrawPoint( X0, Y0 + 1 );
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
pDC->SetPen( cl );
pDC->DrawPoint( X1, Y1 );
}
``````