Wu anti-aliased line

Source: Internet
Author: User

The breshenham algorithm draws lines quickly, but it is not very fine. generally, the integer line can be drawn only on the integer coordinate, which leads to ugly serrations. in a book by Michael Abrash, I saw a good reverse Line Painting and decided to improve it with non-integer coordinates.

A Wu line not only looks better than a normal line, but also produces better animation. A straight line simply jumps from a position to the next position. however, a Wu line is very leisurely drifting to the next position.

  

  

How does it work?

Let's look at what a reverse line actually means. What should an appropriate line look like? How rough is a straight line? What should the tail end be like? A straight line is a one-dimensional object with an infinite length. it has no thickness. the tail end of a line segment does not look like anything. It is just the tail end. such a line cannot be painted on a pixel-based display device.

In computer graphics, it is generally assumed that the line segment is a thick pixel. this means that it can be painted. this also means that he is fine enough to ignore what the end should look like, because it is smaller than a pixel and cannot be painted.

When designing a new Wu line, we must make similar assumptions. because this new algorithm can process non-integer coordinate endpoints, what can be done for a line smaller than one pixel long?

Assume that

. Assume that pixels are in the center of their coordinates.

A straight line is a pixel thick

The shape of the end of a straight line is not important.

It can be better if:

. Two parallel segments with endpoints connected, one of which cannot be distinguished and one of which is a long segment

. The brightness/transparency of a straight line can be defined.

What is the final algorithm?

The final algorithm is quite easy to implement, but it seems too slow in practical application. but it is not really necessary, because its effect is almost the same as that of another faster method. anyway, I will clarify some basic things.

  

  

  

  

Imagine that you can zoom in the pixels of the screen on which we draw a line. The ideal draw line algorithm will calculate the exact area covered by each line to increase

Add the brightness of those pixels.

Such an algorithm is easy to write. In a higher resolution, redraw the relevant part of the screen, draw the line above it, and calculate the covered pixel or

Calculating it presicely.

However, this requires some accuracy. Let's look at the next method.

A more sensible Algorithm

  

  

  

  

  

  

This algorithm draws a pair of pixels across a straight line. A main cycle draws a pair of pixels along the length of the line, and the pixel pairs at the endpoint are calculated separately.

Pixel pair:

Again, a close-up of the screen draws an almost horizontal line.

This almost horizontal line goes through the vertical pixel column. Each time the pixel is crossed, the X coordinate is an integer, but the Y coordinate is not an integer.

A closer look, a single cross point:

In each crossing point, we will consider the pixel pairs of the Cross-ride straight line. The brightness of the two pixels should be 1, and the brightness of the center is the brightness of the ideal straight line.

The brightness of a pixel on a straight line must be proportional to (1-A), and the brightness of a pixel on the line must be proportional to (1-B). That is to say, the pixel closer to a straight line should be brighter.

Draw such a pixel pair along the straight line length, then you basically get a reverse line.

Draw an endpoint

The last thing is to draw the endpoint. this is not easy to handle. I still haven't handled them completely correctly. here is a method I use now. he is not ideal, but very similar. you will notice that when the straight line is almost perpendicular to the horizontal line, it has a careful failure, and the reverse process is also. you will notice this when moving slowly over 45 degrees.

Let's take a closer look at the endpoint:

  

  

We can see an endpoint of a straight line, represented by red points. Blue points represent the center point of the pixel. You can see that the vertex is not in the center point of the pixel.

Calculate the correct brightness of two pixels at the linear endpoint:

. Extend the straight line (backward or forward) to the nearest integer x coordinate (P ). calculate this pixel pair in the same way as the brightness of a common pixel pair on a straight line. then, because the straight line only covers a small part of the pixel (I), the straight line will reduce its brightness. so the brightness should be multiplied by I. therefore, when the entire straight line moves to the right, I will decrease, so that this pixel is dimmed smoothly.

Special Cases

What will happen to a straight line with a length less than one pixel? Because its length is too small to be accurate, you can draw it as needed. this is my own method. I stretch the line to a pixel and then reduce their brightness. so a very short straight line looks very dark. When it gets longer, it will become brighter. When it is a pixel, it will be normally drawn at its position.

Finally, some pseudocode

Some functions required for calculating the number of points in a Wu straight line:

Function trunc (X)

Return integer part of X

End of Function

Function frac (X)

Return fractional part of X

End of Function

Function invfrac (X)

Return 1-(fractional part of X)

End of Function

Wu linear program:

Procedure wuline (fixpt X1, fixpt Y1, fixpt X2, fixpt Y2)

Variable declerations:

Fixpt variables:

Grad, XD, YD, length, XM, ym

Xgap, ygap, xend, yend, XF, YF

Brigheness1, brigheness2

Integer Variables:

X, Y, ix1, ix2, iy1, iy2

Byte variables:

C1, C2

Code starts here:

Width and height of the line

XD = (x2-x1)

YD = (y2-y1)

If ABS (xd)> ABS (YD) then check line gradient

Horizontal (ISH) lines

If x1> X2 then if line is back to front

Swap X1 and X2 then swap it round

Swap Y1 and Y2

XD = (x2-x1)

And recalc XD & YD

YD = (y2-y1)

End if

Grad = YD/XD

Gradient of the line

End Point 1

-----------

Xend = trunc (X1 +. 5)

Find nearest integer x-Coordinate

Yend = Y1 + grad * (xend-x1)

And corresponding y value

Xgap = invfrac (X1 +. 5)

Distance I

Ix1

= Int (xend)

Calc screen coordinates

Iy1

= Int (yend)

Brightness1 = invfrac (yend) * xgap

Calc the intensity of the other

Brightness2 =

Frac (yend) * xgap

End Point pixel pair.

C1 = byte (brightness1 * maxpixelvalue) calc pixel values

C2 = byte (brightness2 * maxpixelvalue)

Drawpixel (ix1, iy1), C1

Draw the pair of pixels

Drawpixel (ix1, iy1 + 1), C2

YF = yend + grad

Calc first y-intersection

Main Loop

End Point 2

-----------

Xend = trunc (X2 +. 5)

Find nearest integer x-Coordinate

Yend = y2 + grad * (xend-x2)

And corresponding y value

Xgap = invfrac (x2-. 5)

Distance I

Ix2

= Int (xend)

Calc screen coordinates

Iy2

= Int (yend)

Brightness1 = invfrac (yend) * xgap

Calc the intensity of the first

Brightness2 =

Frac (yend) * xgap

End Point pixel pair.

C1 = byte (brightness1 * maxpixelvalue) calc pixel values

C2 = byte (brightness2 * maxpixelvalue)

Drawpixel (ix2, iy2), C1 draw the pair of pixels

Drawpixel (ix2, iy2 + 1), C2

Main Loop

---------

Loop X from (ix1 + 1) to (ix2-1) Main Loop

Brightness1 = invfrac (YF)

Calc pixel brightnesses

Brightness2 =

Frac (YF)

C1 = byte (brightness1 * maxpixelvalue) calc pixel values

C2 = byte (brightness2 * maxpixelvalue)

Drawpixel (x, INT (YF), C1 draw the pair of pixels

Drawpixel (x, INT (YF) + 1), C2

YF = YF + grad update the Y-Coordinate

End of X loop end of Loop

Else

Vertical (ISH) lines

Handle the vertical (ISH) lines in

Same way as the horizontal (ISH) ones

But swap the roles of X and Y

End if

End of procedure

Here is a more detailed description of the algorithm mentioned above. For convenience and speed, I used a fixed number of points here. In this case, it is obviously very convenient.

First, I have defined some functions.

Last

It turns out to work and looks amazing.

  

This program draws a Newton's cradle in two resolutions to demonstrate that Wu's straight lines can draw small things and still look OK. You can see how smooth they move.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.