Вы находитесь на странице: 1из 9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

Articles Multimedia GDI General

Antialiasing: Wu Algorithm
.Suchit, 6 Nov 2007
4.95 40 votes

Generating smooth lines with antialiasing; sample code for animation is included

Download demo executable 5.97 KB


Download VC++ source & workspace 19.7 KB

Table of Contents
Introduction
Background
Using the Code
Demo: Spokes Animation
DrawWuLine Function
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

1/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

Resources
Credits

Introduction
Jagged lines are major obstacles in achieving professional displays of raster graphics.
Antialiasing can produce very smooth lines and provide a stylish appearance. You must already
have observed goodlooking antialiased diagrams in PowerPoint 2003. They look very smooth.
Although GDI+ offers antialiasing, most computers may not have its redistributable. With .NET,
you get antialiasing, but again, most computers may not have the .NET framework available. So I
prefer writing "Windows portable" programs in VC++ 6. Hence, here is an MFC version of the
Wu Antialiasing Algorithm.

Background
Research has led to the creation of several techniques for antialiasing. Graphics textbooks like
Foley, Van Dam discuss the GuptaSproul and related algorithms. For fast antialiasing, Xiaolin Wu
invented an algorithm called by his name: Wu Antialiasing. Michael Abrash's Graphics
Programming Black Book gives excellent treatment of this algorithm. Hugo Elias also has an
excellent article on the matter; I strongly recommend reading this one. However, neither have
MFCusable code, so I have implemented their code on MFC.
I wrote a simple WuCircle routine to generate a circle made up of line segments. Now let's see
difference that we achieve by using this implementation. Figure 2 shows the zoomed views of
the above spokes. The image on the left side shows normal drawing. The jagged edges are
clearly visible in it. The rightside image is the antialiased drawing and we can see the smoothing
achieved using "GrayScale" intensities.

http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

2/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

Using the Code


You can reuse the function DrawWuLine. Just call it anywhere you need to draw an antialiased
line.
voidDrawWuLine(CDC*pDC,shortX0,shortY0,shortX1,shortY1,
shortBaseColor,shortNumLevels,unsignedshortIntensityBits);
/*
Arguments:
+pDCiswherelineisdrawn.Canbememorydevicecontext.
+(X0,Y0)isstartpointofline.
+(X1,Y1)isendpointofline.
+BaseColorisintensityofline.Pass0forblackline.
+NumLevelsisnumberofgrayscalelevels.Pass256.
+IntensityBitsdenotesbitsusedtorepresentcolorcomponent.Pass8.
Note:NumLevelsandIntensityBitshave
beenpreservedfromMichaelAbrash'simplementation.
Theycomeveryhandyincustomizingdrawing
algorithmondifferentgraphicshardware.
Youmayhardcodethem.
*/

There is a simple routine for circle generation, which you can reuse. Internally, it calls the line
routine explained above.
voidDrawWuCirlce(CDC*pDC,intx,inty,intr);
/*
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

3/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

Arguments:
+pDCiswherecircleisdrawn.Canbememorydevicecontext.
+(x,y)iscenterofcircle.
+risradiusofcircle.
*/

Both functions can be easily modified to use HDC instead of CDC*, in case you are writing non
MFC Win32 applications.

Demo: Spokes Animation


This application generates some spokes and concentric circles using both "normal" GDI non
antialiased and antialiased line routines. You can press the "a" key to toggle the animation. The
animated wheels show a clear distinction between antialiased and normal line drawing.

RotorThread is a routine that animates spooked wheels. It uses a memory bitmap and a device
context. At ~20 fps frames per second, it rotates the wheels on a memory bitmap. Using
BitBlt, the drawing is brought on the main window.
Pressing "a" again terminates the thread.
UINTRotorThread(LPVOIDlpVoid)
{
bool*pbStop=(bool*)lpVoid;
CWnd*pWnd=AfxGetMainWnd();
CDC*pDC=pWnd>GetDC();
CRectrect;
pWnd>GetClientRect(&rect);
CDCmemDC;
memDC.CreateCompatibleDC(pDC);
CBitmapbitmap;
bitmap.CreateCompatibleBitmap(pDC,
rect.Width(),rect.Height());
memDC.SelectObject(&bitmap);
CFontfont;
font.CreatePointFont(185,"Verdana",&memDC);
memDC.SelectObject(&font);
memDC.SetTextAlign(TA_CENTER);
floatphase=0.0f;
while(!(*pbStop))
{
//1.EraseBackground.
memDC.Rectangle(0,0,rect.Width(),rect.Height());
//2.Drawnewcontents.
memDC.TextOut(100,15,"Normal");
memDC.TextOut(350,15,"Antialiased");
shortx,y;
for(floattheta=phase;theta<
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

4/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

360+phase;theta+=10)
{
x=(short)(100.0*cos(theta*3.14/180.0)+355.0);
y=(short)(100.0*sin(theta*3.14/180.0)+155.0);
DrawWuLine(&memDC,x,y,355,155,0,256,8);
memDC.MoveTo(x240,y);
memDC.LineTo(115,155);
}
//3.Blitdrawingonscreen.
pDC>BitBlt(0,0,rect.Width(),rect.Height(),
&memDC,0,0,SRCCOPY);
//4.Updateanimationparameter.
phase+=1;
::Sleep(67);//15fps.
}
font.DeleteObject();
bitmap.DeleteObject();
memDC.DeleteDC();
pWnd>ReleaseDC(pDC);
return0;
}

DrawWuLine Function
Here is the implementation of the DrawWuLine function:
voidDrawWuLine(CDC*pDC,shortX0,shortY0,shortX1,shortY1,
shortBaseColor,shortNumLevels,unsignedshortIntensityBits)
{
unsignedshortIntensityShift,ErrorAdj,ErrorAcc;
unsignedshortErrorAccTemp,Weighting,WeightingComplementMask;
shortDeltaX,DeltaY,Temp,XDir;
/*Makesurethelinerunstoptobottom*/
if(Y0>Y1){
Temp=Y0;Y0=Y1;Y1=Temp;
Temp=X0;X0=X1;X1=Temp;
}
/*Drawtheinitialpixel,whichisalwaysexactlyintersectedby
thelineandsoneedsnoweighting*/
DrawPixel(pDC,X0,Y0,BaseColor);
if((DeltaX=X1X0)>=0){
XDir=1;
}else{
XDir=1;
DeltaX=DeltaX;/*makeDeltaXpositive*/
}
/*Specialcasehorizontal,vertical,anddiagonallines,which
requirenoweightingbecausetheygorightthroughthecenterof
everypixel*/
if((DeltaY=Y1Y0)==0){
/*Horizontalline*/
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

5/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

while(DeltaX!=0){
X0+=XDir;
DrawPixel(pDC,X0,Y0,BaseColor);
}
return;
}
if(DeltaX==0){
/*Verticalline*/
do{
Y0++;
DrawPixel(pDC,X0,Y0,BaseColor);
}while(DeltaY!=0);
return;
}
if(DeltaX==DeltaY){
/*Diagonalline*/
do{
X0+=XDir;
Y0++;
DrawPixel(pDC,X0,Y0,BaseColor);
}while(DeltaY!=0);
return;
}
/*Lineisnothorizontal,diagonal,orvertical*/
ErrorAcc=0;/*initializethelineerroraccumulatorto0*/
/*#ofbitsbywhichtoshiftErrorAcctogetintensitylevel*/
IntensityShift=16IntensityBits;
/*Maskusedtoflipallbitsinanintensityweighting,producingthe
result(1intensityweighting)*/
WeightingComplementMask=NumLevels1;
/*IsthisanXmajororYmajorline?*/
if(DeltaY>DeltaX){
/*Ymajorline;calculate16bitfixedpointfractionalpartofa
pixelthatXadvanceseachtimeYadvances1pixel,truncatingthe
resultsothatwewon'toverruntheendpointalongtheXaxis*/
ErrorAdj=((unsignedlong)DeltaX<<16)/(unsignedlong)DeltaY;
/*Drawallpixelsotherthanthefirstandlast*/
while(DeltaY){
ErrorAccTemp=ErrorAcc;/*remembercurrrentaccumulatederror*/
ErrorAcc+=ErrorAdj;/*calculateerrorfornextpixel*/
if(ErrorAcc<=ErrorAccTemp){
/*Theerroraccumulatorturnedover,soadvancetheXcoord*/
X0+=XDir;
}
Y0++;/*Ymajor,soalwaysadvanceY*/
/*TheIntensityBitsmostsignificantbitsofErrorAccgiveusthe
intensityweightingforthispixel,andthecomplementofthe
weightingforthepairedpixel*/
Weighting=ErrorAcc>>IntensityShift;
DrawPixel(pDC,X0,Y0,BaseColor+Weighting);
DrawPixel(pDC,X0+XDir,Y0,
BaseColor+(Weighting^WeightingComplementMask));
}
/*Drawthefinalpixel,whichis
alwaysexactlyintersectedbytheline
andsoneedsnoweighting*/
DrawPixel(pDC,X1,Y1,BaseColor);
return;
}
/*It'sanXmajorline;calculate16bitfixedpointfractionalpartofa
pixelthatYadvanceseachtimeXadvances1pixel,truncatingthe
resulttoavoidoverrunningtheendpointalongtheXaxis*/
ErrorAdj=((unsignedlong)DeltaY<<16)/(unsignedlong)DeltaX;
/*Drawallpixelsotherthanthefirstandlast*/
while(DeltaX){
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

6/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

ErrorAccTemp=ErrorAcc;/*remembercurrrentaccumulatederror*/
ErrorAcc+=ErrorAdj;/*calculateerrorfornextpixel*/
if(ErrorAcc<=ErrorAccTemp){
/*Theerroraccumulatorturnedover,soadvancetheYcoord*/
Y0++;
}
X0+=XDir;/*Xmajor,soalwaysadvanceX*/
/*TheIntensityBitsmostsignificantbitsofErrorAccgiveusthe
intensityweightingforthispixel,andthecomplementofthe
weightingforthepairedpixel*/
Weighting=ErrorAcc>>IntensityShift;
DrawPixel(pDC,X0,Y0,BaseColor+Weighting);
DrawPixel(pDC,X0,Y0+1,
BaseColor+(Weighting^WeightingComplementMask));
}
/*Drawthefinalpixel,whichisalwaysexactlyintersectedbytheline
andsoneedsnoweighting*/
DrawPixel(pDC,X1,Y1,BaseColor);
}

Colored Version of WuLine


A colored version of the WuLine is available here.
I hope this will come in handy for some of your applications.

Resources
Good reference materials:
Michael Abrash's Graphics Programming Black Book.
Hugo Elias' Theory of Wu Lines.
Textbook: Computer Graphics by Foley, Van Dam et. al.

Credits
Eien posted a colored version of the algorithm that I had planned as the next installment, for
simplicity.
Thank you, Eien!

Updates
The entire code for this has been hosted at Google Code to enable Open Source development.
Please feel free to join that development group and contribute to it. At the moment, the FLTK
project is using this work.
Your comments and suggestions are always welcome. Just post here.

http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

7/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

History
8 March 2006 Original version posted
10 March, 2006 Article moved
6 November, 2007 Article contents updated

License
This article has no explicit license attached to it but may contain usage terms in the article text or
the download files themselves. If in doubt please contact the author via the discussion board
below.
A list of licenses authors might use can be found here

Share
About the Author
.Suchit
Architect GE India Innovation Center
India

Suchit is an Architect at GE India Innovation Center, Hyderabad.

He architected and developed portions of Proficy RX, a Process Analytical Technology PAT
Solution of GE Fanuc Intelligent Platforms.

He also is the Architect of OPC Server for hardware devices of GE Sensing. These devices
sense temperature, humidity, combustibles, fluid flow, pressure and various engineering
parameters primarily used in Industrial Automation & Process Control applications.

Interests: Computer Graphics, Mathematical Modeling, Scientific Applications Development.

http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

8/9

26/1/2015

Antialiasing:WuAlgorithmCodeProject

He lives in Hyderabad India with his wife and 2 kidbots. Loves reading books if these 2 small
buddies allow him to.

Homepage : http://www.SuchitTiwari.Org

Comments and Discussions


26 messages have been posted for this article Visit
http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm to post and view
comments on this article, or click here to get a print view with messages.
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150123.1 | Last Updated 6 Nov 2007

Seleccionar idioma

http://www.codeproject.com/Articles/13360/AntialiasingWuAlgorithm?display=Print

Article Copyright 2006 by .Suchit


Everything else Copyright CodeProject, 19992015

9/9