抗锯齿:Wu算法

分享于 

9分钟阅读

多媒体

  繁體
  • 下载演示可执行文件-5.97 KB
  • Download VC++ source & workspace - 19.7 KB
  • 介绍

    锯齿是实现光栅图形专业显示的主要障碍,抗锯齿可以产生非常平滑的线条,并提供时尚的外观,在PowerPoint 2003中,你必须已经看到好看的抗锯齿图表,用. NET,自动就有了抗锯齿功能,但大多数计算机可能没有.NET框架可用。

    背景

    使用代码

    可以重用函数DrawWuLine

    void DrawWuLine (CDC *pDC, short X0, short Y0, short X1, short Y1,
     short BaseColor, short NumLevels, unsignedshort IntensityBits);/*Arguments:
     + pDC is where line is drawn. Can be memory device context.
     + (X0,Y0) is start point of line.
     + (X1, Y1) is end point of line.
     + BaseColor is intensity of line. Pass 0 for black line.
     + NumLevels is number of gray scale levels. Pass 256.
     + IntensityBits denotes bits used to represent color component. Pass 8.
    Note: NumLevels and IntensityBits have
    been preserved from Michael Abrash's implementation.
    They come very handy in customizing drawing
    algorithm on different graphics hardware.
    You may hardcode them.
    */

    有一个用于生成圆的简单例程,可以重复使用。

    void DrawWuCirlce (CDC * pDC, int x, int y, int r);/*Arguments:
     + pDC is where circle is drawn. Can be memory device context.
     + (x,y) is center of circle.
     + r is radius of circle.
    */

    如果要编写非MFC Win32应用程序,则可以轻松地将这两个函数修改为使用HDC而不是CDC *。

    演示:Spokes Animation

    这个应用程序使用"正常"GDI (非抗锯齿)和antialiased line例程生成一些辐条和同心圆,

    RotorThread是一个设置弯曲车轮动画的例程,它使用内存位图和设备上下文,~20 fps (每秒帧数),它回滚内存位图上的轮子,使用BitBlt,绘图被带到主窗口。

    UINT RotorThread (LPVOID lpVoid)
    {
     bool * pbStop = (bool *) lpVoid;
     CWnd * pWnd = AfxGetMainWnd();
     CDC * pDC = pWnd->GetDC();
     CRect rect;
     pWnd->GetClientRect (&rect);
     CDC memDC;
     memDC.CreateCompatibleDC (pDC);
     CBitmap bitmap;
     bitmap.CreateCompatibleBitmap (pDC,
     rect.Width(), rect.Height());
     memDC.SelectObject (&bitmap);
     CFont font;
     font.CreatePointFont (185, "Verdana", &memDC);
     memDC.SelectObject (&font);
     memDC.SetTextAlign (TA_CENTER);
     float phase = 0.0f;
     while (!(*pbStop))
     {
     //1. Erase Background. memDC.Rectangle (0, 0, rect.Width(), rect.Height());
     //2. Draw new contents. memDC.TextOut (100, 15, "Normal");
     memDC.TextOut (350, 15, "Anti-aliased");
     short x, y;
     for (float theta= phase; theta<
     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 (x-240,y);
     memDC.LineTo (115,155);
     }
     //3. Blit drawing on screen. pDC->BitBlt (0, 0, rect.Width(), rect.Height(),
     &memDC, 0, 0, SRCCOPY);
     //4. Update animation parameter. phase += 1;
     ::Sleep (67); //15 fps. }
     font.DeleteObject();
     bitmap.DeleteObject();
     memDC.DeleteDC();
     pWnd->ReleaseDC (pDC);
     return0;
    }

    DrawWuLine函数

    下面是DrawWuLine函数的实现:

    void DrawWuLine (CDC *pDC, short X0, short Y0, short X1, short Y1,
     short BaseColor, short NumLevels, unsignedshort IntensityBits)
    {
     unsignedshort IntensityShift, ErrorAdj, ErrorAcc;
     unsignedshort ErrorAccTemp, Weighting, WeightingComplementMask;
     short DeltaX, DeltaY, Temp, XDir;
     /* Make sure the line runs top to bottom */if (Y0> Y1) {
     Temp = Y0; Y0 = Y1; Y1 = Temp;
     Temp = X0; X0 = X1; X1 = Temp;
     }
     /* Draw the initial pixel, which is always exactly intersected by
     the line and so needs no weighting */ DrawPixel(pDC,X0, Y0, BaseColor);
     if ((DeltaX = X1 - X0)> = 0) {
     XDir = 1;
     } else {
     XDir = -1;
     DeltaX = -DeltaX; /* make DeltaX positive */ }
     /* Special-case horizontal, vertical, and diagonal lines, which
     require no weighting because they go right through the center of
     every pixel */if ((DeltaY = Y1 - Y0) == 0) {
     /* Horizontal line */while (DeltaX--!= 0) {
     X0 += XDir;
     DrawPixel(pDC,X0, Y0, BaseColor);
     }
     return;
     }
     if (DeltaX == 0) {
     /* Vertical line */do {
     Y0++;
     DrawPixel(pDC,X0, Y0, BaseColor);
     } while (--DeltaY!= 0);
     return;
     }
     if (DeltaX == DeltaY) {
     /* Diagonal line */do {
     X0 += XDir;
     Y0++;
     DrawPixel(pDC,X0, Y0, BaseColor);
     } while (--DeltaY!= 0);
     return;
     }
     /* Line is not horizontal, diagonal, or vertical */ ErrorAcc = 0; /* initialize the line error accumulator to 0 *//* # of bits by which to shift ErrorAcc to get intensity level */ IntensityShift = 16 - IntensityBits;
     /* Mask used to flip all bits in an intensity weighting, producing the
     result (1 - intensity weighting) */ WeightingComplementMask = NumLevels - 1;
     /* Is this an X-major or Y-major line? */if (DeltaY> DeltaX) {
     /* 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 = ((unsignedlong) DeltaX <<16)/(unsignedlong) DeltaY;
     /* Draw all pixels other than the first and last */while (--DeltaY) {
     ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ ErrorAcc += ErrorAdj; /* calculate error for next pixel */if (ErrorAcc <= ErrorAccTemp) {
     /* The error accumulator turned over, so advance the X coord */ X0 += XDir;
     }
     Y0++; /* 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;
     DrawPixel(pDC,X0, Y0, BaseColor + Weighting);
     DrawPixel(pDC,X0 + XDir, Y0,
     BaseColor + (Weighting ^ WeightingComplementMask));
     }
     /* Draw the final pixel, which is 
     always exactly intersected by the line
     and so needs no weighting */ DrawPixel(pDC,X1, Y1, BaseColor);
     return;
     }
     /* 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 = ((unsignedlong) DeltaY <<16)/(unsignedlong) DeltaX;
     /* Draw all pixels other than the first and last */while (--DeltaX) {
     ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ ErrorAcc += ErrorAdj; /* calculate error for next pixel */if (ErrorAcc <= ErrorAccTemp) {
     /* The error accumulator turned over, so advance the Y coord */ Y0++;
     }
     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;
     DrawPixel(pDC,X0, Y0, BaseColor + Weighting);
     DrawPixel(pDC,X0, Y0 + 1,
     BaseColor + (Weighting ^ WeightingComplementMask));
     }
     /* Draw the final pixel, which is always exactly intersected by the line
     and so needs no weighting */ DrawPixel(pDC,X1, Y1, BaseColor);
    }

    WuLine的彩色版本

  • WuLine的彩色版本在此提供
  • 更新

    完整的代码位于Google Code


    算法  ANT  反混淆  
    相关文章