Re: Anti-aliased drawing

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



I'll give this a go. The problem will be modifying it to draw arc's, I
suspect.

"Mike Williams" <mikea@xxxxxxxxxxxxxxxxx> wrote in message
news:OqV9QY9%23IHA.3392@xxxxxxxxxxxxxxxxxxxxxxx
"Steve Barnett" <noname@xxxxxxxxxxxx> wrote in message
news:%235kap87%23IHA.3928@xxxxxxxxxxxxxxxxxxxxxxx

It's the problem of drawing the 70% arc in red without
the jagged edges that I'm struggling with.

You need to draw an antialiaised line and then fill the required area (or
perhaps the other way round, I can't quite remember the best technique).
There are various techniques for drawing AA lines (or alternatively you
can use GDI+ of course which I think will draw them natively for you).
Here is one method which does not require GDI+. Paste the following code
into a VB Form containing one Line Control. The Line Control is only
required to simplify the interface which allows you to drag out the line
you wish to draw, it has nothing whatsoever to do with the drawing of the
line itself, which is in fact done by the DrawWuLine routine. Run the code
and use the mouse to draw some lines:

Mike

Option Explicit
Private Declare Function GetPixel Lib "GDI32.dll" _
(ByVal hDC As Long, _
ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function SetPixelV Lib "GDI32.dll" _
(ByVal hDC As Long, _
ByVal X As Long, ByVal Y As Long, _
ByVal crColor As Long) As Long
Private xStart As Long, yStart As Long

Private Sub DrawWuLine(ByVal inDC As Long, _
ByVal X0 As Long, ByVal Y0 As Long, _
ByVal X1 As Long, ByVal Y1 As Long, ByVal inCol As Long)
' Function to draw an antialiased line from (X0,Y0)
' to (X1,Y1), using an antialiasing approach published
' by Xiaolin Wu in the July 1991 issue of
' Computer Graphics.
Dim ErrorAdj As Long, ErrorAcc As Long
Dim ErrorAccTemp As Long, Weighting As Long
Dim DeltaX As Long, DeltaY As Long, Temp As Long
Dim XDir As Long
Dim ColR As Long, ColG As Long, ColB As Long
ColR = inCol And &HFF&
ColG = (inCol And &HFF00&) \ &H100&
ColB = (inCol And &HFF0000) \ &H10000
' # of bits to shift ErrorAcc to get intensity level
Const IntensityShift As Long = &H100&
' Mask used to flip all bits in an intensity weighting,
' producing the' result (1 - intensity weighting)
Const WeightingComplementMask As Long = &HFF&
Const FullAlpha As Long = &HFF&
' Make sure the line runs top to bottom
If (Y0 > Y1) Then
Temp = Y0
Y0 = Y1
Y1 = Temp
Temp = X0
X0 = X1
X1 = Temp
End If
' Draw the initial pixel, which is always exactly
' intersected by the line and so needs no weighting
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, FullAlpha)
DeltaX = X1 - X0
If (DeltaX >= 0) Then
XDir = 1
Else
XDir = -1
DeltaX = -DeltaX ' make DeltaX positive
End If
' Special-case horizontal, vertical, and diagonal lines,
' which require no weighting because they go right
' through the center of every pixel
DeltaY = Y1 - Y0
If (DeltaY = 0) Then ' Horizontal line
Do While (DeltaX <> 0)
X0 = X0 + XDir
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, FullAlpha)
DeltaX = DeltaX - 1
Loop
ElseIf (DeltaX = 0) Then ' Vertical line
Do
Y0 = Y0 + 1
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, FullAlpha)
DeltaY = DeltaY - 1
Loop While (DeltaY)
ElseIf (DeltaX = DeltaY) Then ' Diagonal line
Do
X0 = X0 + XDir
Y0 = Y0 + 1
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, FullAlpha)
DeltaY = DeltaY - 1
Loop While (DeltaY)
Else ' Line is not horizontal, diagonal, or vertical
ErrorAcc = 0 ' initialize line error accumulator to 0
' Is this an X-major or Y-major line?
If (DeltaY > DeltaX) Then
' 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 = (DeltaX * &H10000) \ DeltaY ' <<16
' Draw all pixels other than the first and last
Do While (DeltaY)
' remember currrent accumulated error */
ErrorAccTemp = ErrorAcc
' calculate error for next pixel */
ErrorAcc = (ErrorAcc + ErrorAdj) And &HFFFF&
If (ErrorAcc <= ErrorAccTemp) Then
' The error accumulator turned over, so advance
' the X coord
X0 = X0 + XDir
End If
Y0 = Y0 + 1 ' 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
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, _
Weighting Xor WeightingComplementMask)
Call DrawPixel(inDC, X0 + XDir, Y0, ColR, ColG, _
ColB, Weighting)
DeltaY = DeltaY - 1
Loop
' Draw the final pixel, which is always exactly
' intersected by the line and so needs no weighting
Call DrawPixel(inDC, X1, Y1, ColR, ColG, ColB, _
FullAlpha)
Exit Sub
End If
' 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 = (DeltaY * &H10000) \ DeltaX
' Draw all pixels other than the first and last
Do While (DeltaX)
' remember currrent accumulated error
ErrorAccTemp = ErrorAcc
' calculate error for next pixel
ErrorAcc = (ErrorAcc + ErrorAdj) And &HFFFF&
If (ErrorAcc <= ErrorAccTemp) Then
' The error accumulator turned over, so advance
' the Y coord
Y0 = Y0 + 1
End If
X0 = 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
Call DrawPixel(inDC, X0, Y0, ColR, ColG, ColB, _
Weighting Xor WeightingComplementMask)
Call DrawPixel(inDC, X0, Y0 + 1, ColR, ColG, ColB, _
Weighting)
DeltaX = DeltaX - 1
Loop
' Draw the final pixel, which is always exactly
' intersected by the line and so needs no weighting
Call DrawPixel(inDC, X1, Y1, ColR, ColG, ColB, _
FullAlpha)
End If
End Sub

Private Sub DrawPixel(ByVal inDC As Long, _
ByVal inX As Long, ByVal inY As Long, _
ByVal inR As Long, ByVal inG As Long, _
ByVal inB As Long, ByVal inA As Long)
Dim SrcCol As Long
Dim InvAlpha As Long
If (inA = &HFF) Then
Call SetPixelV(inDC, inX, inY, RGB(inR, inG, inB))
ElseIf (inA) Then
InvAlpha = inA Xor &HFF&
SrcCol = GetPixel(inDC, inX, inY)
Call SetPixelV(inDC, inX, inY, _
(((((SrcCol And &HFF&) * InvAlpha) + (inR * inA)) _
And &HFF00&) \ &H100) Or (((((SrcCol And &HFF00&) _
\ &H100&) * InvAlpha) + (inG * inA)) And &HFF00&) _
Or ((((((SrcCol And &HFF0000) \ &H10000) * _
InvAlpha) + (inB * inA)) And &HFF00&) * &H100&))
End If
End Sub

Private Sub Form_Load()
Me.BackColor = vbWhite
Me.ForeColor = vbBlue
Me.ScaleMode = vbPixels
Me.AutoRedraw = True
Line1.Visible = False
End Sub

Private Sub Form_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If (Button And 1) = vbLeftButton Then
Line1.X1 = X
Line1.Y1 = Y
Line1.X2 = X
Line1.Y2 = Y
Line1.BorderColor = Me.ForeColor
Line1.Visible = True
End If
End Sub

Private Sub Form_MouseMove(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If Line1.Visible = True Then
Line1.X2 = X
Line1.Y2 = Y
End If
End Sub

Private Sub Form_MouseUp(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If (Button And 1) = vbLeftButton Then
Line1.Visible = False
Call DrawWuLine(Me.hDC, Line1.X1, Line1.Y1, _
Line1.X2, Line1.Y2, Me.ForeColor)
End If
End Sub








.



Relevant Pages

  • Re: Line Drawing
    ... Dim ErrorAdj As Long, ErrorAcc As Long ... Dim ErrorAccTemp As Long, Weighting As Long ... Dim DeltaX As Long, DeltaY As Long, Temp As Long ... ' Draw the initial pixel, ...
    (microsoft.public.vb.general.discussion)
  • Re: Line Drawing
    ... Dim ErrorAdj As Long, ErrorAcc As Long ... Dim ErrorAccTemp As Long, Weighting As Long ... Dim DeltaX As Long, DeltaY As Long, Temp As Long ... ' Draw the initial pixel, ...
    (microsoft.public.vb.general.discussion)
  • Re: Anti-aliased drawing
    ... You need to draw an antialiaised line and then fill the required area. ... Dim ErrorAdj As Long, ErrorAcc As Long ... Dim ErrorAccTemp As Long, Weighting As Long ... ' Draw the initial pixel, ...
    (microsoft.public.vb.general.discussion)
  • Re: Draw pixel
    ... picture box, but instead draw right onto the form. ... simple example, I would want to draw a square, pixel by pixel to the ... Private Declare Function SetPixel Lib "gdi32" _ ...
    (comp.lang.basic.visual.misc)
  • Re: difference between drawrectangle and fillrectangle
    ... anti-aliasing. ... is at pixel 10.5, and the center of coordinate 12 is at pixel 12.5, the pen ... If you draw with SmoothingMode set to AntiAlias, you will see the fill now ... pens always draw a figure that is increased in width and height ...
    (microsoft.public.dotnet.framework.drawing)