Click here to Skip to main content
Click here to Skip to main content

CTGraphics - Anti-Alias C++ Drawing

By , 13 Dec 2006
 

Demo-Project Screenshot image

Introduction

This article is about the anti-alias drawing support under GDI using C++. It refers to MFC or non-MFC applications. Here, a small class called CTGraphics is presented. It has anti-alias support for drawing basic primitives: lines, arcs, ellipses (circles), round rectangles, polylines, and pies. You can define other interesting shapes using this basic primitives.

Background

What is the "aliasing" effect? It is the effect of jagged-edges (or stairs in other words) that appear when you draw some graphic shapes using the basic Windows GDI. See the image below:

Aliased Line image

So what is the problem with this? Well, if you want your computer generated graphics (or images) to look nice, this is not a good way to do it. How does this happen then? It is because of the limited screen resolution, that is a limited number of pixels, horizontal or vertical, that can be drawn on the screen. Their size is so small that you can't see them, so that is why this will happen when you want to draw a line using the MoveToEx() and LineTo() methods of the Windows GDI.

What to do then? Now, this is a place where a technique called "anti-aliasing" is coming at the scene. It must do something to blur those edges so different approaches were taken for this action. One is called a super-sampling of the original image. It renders an image at high frequency (scaled original image 2x or more), and then it performs low-pass filtering of that super-sampled image so the edges will become less sharp, and when you scale this image down again (to the original size), you will have an anti-aliasing effect in action. This is a very memory consuming method but it will work.

Another method (implemented here) is the so called pre-filtering of the original image. It averages the amount of pixels that is covered with the primitive equation. The ideal line will not cover the whole pixel but a part of it, so this method sets the intensity of that pixel to some value other than the maximum for the line that you are drawing. So while you draw your line, you set the line pixels to some value. This method is less memory consuming than the previous one but it takes a lot of math to implement it to work correctly, so you can see where the compromise is.

Whichever way you do anti-aliasing, you will get an output similar to the following:

AntiAliased Line image

So, you have modified the original line pixels so that now line edges are a bit smoothed. The CTGraphics class does its work in a similar manner. It supports anti-aliasing for the following:

  • Lines
  • Polylines
  • Polygons
  • Ellipses
  • Arcs
  • Pies
  • Chords
  • Round Rectangles
  • Bezier Splines

However, you are free to extend its functionality on other shapes and graphic primitives. You can combine basic shapes and get more complex shapes (this is how the Round Rectangle is done: by combining Lines and Arcs).

Using the code

To use the source provided, just include the TGraphics.h and TGraphics.cpp files in your MS Visual C++ Project. Using the described class is very simple, see below:

CTGraphics tGraphics;

// hDC is obtained somewhere else
// Variables x1, y1, x2 and y2 are defined somewhere else
COLORREF color = RGB(255, 0, 0); // Pick some nice line color

// You have everything, now draw anti-aliased line
tGraphics.DrawLine(hDC, x1, y1, x2, y2, color);

It is very simple, isn't it? Other methods of the CTGraphics class work very similar so I will not explain each of them.

Important note

Here is presented a small C++ class which performs anti-aliased drawing using Windows GDI and C++. However, no speed records were a goal here, so don't expect the demo to run the fastest it can. This is just the demo of the functionality that was required to have smooth edges while drawing lines and arcs, at the first place. Also, just 1px width of the "drawing pen" is supported. This may sound not perfect, but this was only done in order to finish the job, not to make it harder than it already is.

Points of interest

I was looking for this subject all over the Internet and CodeProject and found different solutions, more or less similar. I wanted to extend the basic line anti-aliasing algorithms (like Wu's algorithm present on the CodeProject) to arcs and other shapes. I don't say this is the best result you can achieve, but it finished the job for me very quickly. You also may find that, due to float numbers involved in the calculations, the output is not perfect, but I leave this as an exercise for you. As an example of different approaches, you may find in the source of the CTGraphics class that ellipse is not done using an arc of 360 degrees, although it could be. Instead I used a similar and a bit modified math equation.

History

CTGraphics class version 1.01.

In this release, the support for the following were added:

  • Polygons
  • Chords
  • Bezier Splines

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

darkoman
Software Developer (Senior) Elektromehanika d.o.o. Nis
Serbia Serbia
Member
He has a master degree in Computer Science at Faculty of Electronics in Nis (Serbia), and works as a C++/C# application developer for Windows platforms since 2001. He likes traveling, reading and meeting new people and cultures.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: How to Fill?memberMukit, Ataul24 Sep '10 - 20:45 
May I add, pressing 'F' Key would help to see the visualization of a filled shape which would be similar to your application screenshot.
QuestionHow to set thickness of line?memberxumingxian20 Aug '07 - 16:04 
Can we set thickness of line?
Questionis this a bug ?membercbeaudet19 Jul '07 - 7:45 
Is this a bug ? (in DrawArc)
 
if (deltaY > 0)
::SetPixel(hDC, centerX+xs, centerY+(int)yt+1, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+xs, centerY+(int)yt+1, RGB(red,green,blue));
 
Those 2 lines seam the same to me (there's the same strange code elsewere)
 
Thanks for that good article...

QuestionThickness of Line?memberAVEbrahimi31 Dec '06 - 20:08 
How to set thickness of line?
AnswerRe: Thickness of Line?memberdarkoman2 Jan '07 - 23:08 
Hello...
 

for now, there is no way to directly set the thickness of the line.
I'll implement this in the future releases.
 
Best regards,
Darko
GeneralRe: Thickness of Line?membermound3 Jan '12 - 5:33 
Nice work! Does the future release exist yet that allows line thickness control?
GeneralPocket PCmemberAVEbrahimi31 Dec '06 - 19:18 
Does this work on Pocket PC?
Confused | :confused:
 
I am going to test it.
 
bill.gates.com@gmail.com
GeneralA good, practical article...memberJun Du16 Dec '06 - 14:46 
This is a great little article, which would be helpful to GDI developers. You've got my 5.
 
I use both GDI and GDI+ and find GDI still has its good places in real world applications. I'd like to see more articles like this.
 
Also, even pixel manipulation is not optimal, it shouldn't be an issue in vector graphics like this case. The number of pixels you touched is only a fraction of the entire display. Raster graphics would be a different story.
 

 
Best,
Jun

GeneralThanks...memberPaul Selormey13 Dec '06 - 13:45 
It will be a nice resource for those of us looking to do custom lines.
 
With love,
Paul.
 
Jesus Christ is LOVE! Please tell somebody.

GeneralPretty damn cool :)memberKochise30 Nov '06 - 21:12 
Just to do some tidy bimap work, this component is far enough ! You can do some work at startup (while the splash makes the user waiting a bit) then using the cached bitmap along the program execution.
 
There is another mathematicaly accurate AA projects somewhere on CP that might be complementary to this object :
 
http://www.codeproject.com/gdi/antialias.asp
http://www.codeproject.com/bitmap/aarot.asp
http://www.codeproject.com/useritems/Aaform.asp
 
Otherwise for a full featured C++ AA rendering engine, try this (but it's as not easy to implement) :
 
http://www.antigrain.com/
 
And yop, beside this, another 5 for another nice job !
 
Kochise

 
In Code we trust !

GeneralRe: Pretty damn cool :)memberPaul Selormey13 Dec '06 - 13:44 
Kochise wrote:
http://www.antigrain.com/

It is now under GPL!
 
With love,
Paul.
 
Jesus Christ is LOVE! Please tell somebody.

GeneralRe: Pretty damn cool :)membermatakk@126.com29 Jan '07 - 19:45 
Thanks to introduce the great lib.
 
Big Grin | :-D
GeneralCoolmemberLeafdown30 Nov '06 - 15:41 
This is just I want.. Thank you.
 
nonw

GeneralGood for learning about AA but....memberScope30 Nov '06 - 9:46 
Unfortunately it is too slow. The get/set-pixel approach could be replaced by using a dib and accessing the pixels directly in memory. But even with that optimization the use of GDI+ would most likely be faster.
GDI+ also use software AA, but that will be changed eventually according to microsoft (perhaps it's already hardware accelerated in vista?).
 
However I would recommend ppl to use GDI+ for AA lines,curves and shapes, since they may benefit from hardware acceleration in the future.
 
Here is the msdn documentation of it :
Antialiasing with Lines and Curves[^]
 

Good effort on this article though, people that wants to know how its done behind the scenes might find this very useful!
 
Keep up the good work
 

 
-----------------------------
I am out of scope

GeneralRe: Good for learning about AA but....memberdarkoman30 Nov '06 - 19:23 
Hello...
 
thanks for your interest.
Yes, I don't think this source can compete with the power of GDI+ but for those not working under .NET this source might be usefull. I very often write applications in plain C++ and I need a good genereted computer graphics for that. Also, if you ever wanted to work under DirectX (DirectDraw component), you may discover that this can be the only way to go.
 

PS.
Although (I didn't mention in the article since it was not an object) you might want to test for the GDI+ anti-alias output (ie. Ellipse shape) and this source.
GeneralRe: Good for learning about AA but....memberHarkos30 Nov '06 - 23:15 
Perhaps all the code needs is a new sight. People have different backgrounds and these can provide enough information to optimize the work already started. I myself will save your article to read when it comes for my project to render graphics.
 
[]'s
Harkos
---
"Money isn't our god, integrity will free our soul."
Cut Throat - Sepultura

GeneralRe: Good for learning about AA but.... [modified]memberScope1 Dec '06 - 1:46 
Hello darkoman!
 
I just had to point out that GDI+ is not a part of the .NET framework. It is included in Windows XP and it is available as a redistributable package for users with Win2000 & Windows9X.
 
Here is an example of a drawline function that use AA in GDI+ :
#pragma comment(lib,"gdiplus.lib")
 
#include <gdiplus.h>
 
using namespace Gdiplus;
 

bool DrawLine( HDC hdc , int x1 , int y1 , int x2 , int y2 , DWORD color , bool useAA = true , bool colorIsCOLORREF = false )
{
	Graphics 	graphics( hdc );
	Color 		col( (ARGB) color );			
	Pen 		pen( col , 1 );
 
	if ( colorIsCOLORREF ) col.SetFromCOLORREF( (COLORREF) color );
 
	return	graphics.SetSmoothingMode( useAA == true ? SmoothingModeAntiAlias : SmoothingModeDefault ) == Ok &&
		graphics.DrawLine( &pen , x1 , y1 , x2 , y2 ) == Ok;
}

 
Oh, and you also have to initialize GDI+, but the point was to show that it can be made in "plain C++" its just a library.
 
Anyway I dont want to ruin your fun, the article is still worth a 5, keep up the good work!
 

-- modified at 8:11 Friday 1st December, 2006
 
-----------------------------
I am out of scope

GeneralRe: Good for learning about AA but....memberdarkoman1 Dec '06 - 2:49 
Thanks again,
 
Yes, there are about 100+ things that should to be done with this class to make it work similar to GDI+, but it makes you feel better when you know you can try.
 
Anyway, with GDI+ (that is, with the whole .NET platform) Microsoft did the excellent job, providing us the way to build graphic based (and other) applications like never before.
 
Regards...
GeneralRe: Good for learning about AA but....memberAdalsteinn B. Bjarnason6 Dec '06 - 10:02 
I want to give Darkoman full credits for his implementation of smooth graphic.
 
Although the Bresnham algorythm has been well known in the computer world
for decades, most of recent programmers have bad taste of jagged graphics.
Sure there are well known solutions available for programmers, some are free
but other notSniff | :^) .
 
Microsoft didn't include that gdiplus.dll into their OS flora until recently.
Was it included with the first version of XP or with service pack one ?
 
Anyhow it is embarassing for most programmers to depend always on third party
COM objects or DLLs. I vote for small useful classes or solutions like CTGraphics
which is easy to import into your project without mangling with GDI+Smile | :) .
 
I suggest using dibsection instead of get/setpixel. It is created by using
CreateDIBSection, palettes can be truncated because XP doesn't support less
than 16 bit color depth.
 
Regards, ABB
GeneralRe: Good for learning about AA but....memberdarkoman6 Dec '06 - 19:44 
Hello...
 
thank you for your comments on this article. I also support direct data-buffer manipulation either in GDI or in DirectX when it comes to "real-world" applications which will use this small class. I used Get/SetPixel just as an example here, since there are just a few things to present to the readers.
 

Best regards,
Darkoman
GeneralRe: Good for learning about AA but....membermohsen nassaji8 Dec '12 - 19:17 
I am looking for an algorithm to draw fat anti-aliased line (I want implement it on C++ and hardware too)
please help me!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 13 Dec 2006
Article Copyright 2006 by darkoman
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid