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:
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:
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