zoukankan      html  css  js  c++  java
  • 基本图形的扫描转换(绘图函数的自定义实现)和反采样。

      基本图形的扫描转换这个名词不太容易理解,通俗地讲就是通过SetPixel或者SetPixelV函数来实现绘图,比如画一条直线会使用LineTo,同样可以用SetPixel函数实现。

      其中SetPixel与SetPixelV的区别,SetPixelV不放回实际像素点的RGB值,执行速度比SetPixel快得多!!!

       

           圆的扫描转换

      既如何自定义绘制圆,而不是通过Ellipse直接绘制,而是通过SetPixelV去绘制。

      1、根据对称性,一个在中心在原点的圆,有4条对称轴x=0,y=0,x=y,x=-y,分成8等分。所以只要绘制出第一象限内的1/8圆弧,通过对称性,可以绘制出整个圆。比如第一象限内圆上某点为(x,y),则另外7个点为(x,-y),(-x,y),(-x,-y),(y,x),(-y,x),(y,-x),(-y,-x);

      2、通过Bresenhma算法可以推得公式 误差di = (xi+1)*(xi+1) + (yi-0.5)*(yi-0.5) - R*R;该公式推理过程可以看孔玲德著作计算机图形学基础教程(第二版96页)。通过现有坐标(xi,yi)推断(xi+1,yi+1)的值。如果di>>=0 yi+1 = yi-1,否则yi+1 = yi。

      通过这两个特点我们可以编写程序,由于第一个特性需要中心在原点,所以我们要自己设置画布的原点正好在圆心。代码如下:

      

        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        SIZE ptOldViewExt,ptOldWindowExt;
        POINT ptOldOrg;
        int OldMapMode = SetMapMode(hdc,MM_ANISOTROPIC);
        int iWidth = abs(rtClient.right - rtClient.left);
        int iHeight = abs(rtClient.bottom - rtClient.top);
        SetViewportExtEx(hdc,iWidth,iHeight,&ptOldViewExt);
        SetWindowExtEx(hdc,iWidth,-iHeight,&ptOldWindowExt);
        POINT ptOrg = {pt.x,pt.y};
        DPtoLP(hdc,&ptOrg,1);
        SetWindowOrgEx(hdc,-ptOrg.x,-ptOrg.y,&ptOldOrg); 

      绘制结束需要复原坐标,这是一个好习惯!

       SetViewportExtEx(hdc,ptOldViewExt.cx,ptOldViewExt.cy,NULL);
        SetWindowExtEx(hdc,ptOldWindowExt.cx,ptOldWindowExt.cy,NULL);
        SetWindowOrgEx(hdc,ptOldOrg.x,ptOldOrg.y,NULL);

      并且根据对称性,我们可以写一下函数

      

    VOID DrawAxial(HDC hdc,int x,int y,COLORREF color)
    {
        SetPixelV(hdc,x,y,color);
        SetPixelV(hdc,x,-y,color);
        SetPixelV(hdc,-x,y,color);
        SetPixelV(hdc,-x,-y,color);
        SetPixelV(hdc,y,x,color);
        SetPixelV(hdc,y,-x,color);
        SetPixelV(hdc,-y,x,color);
        SetPixelV(hdc,-y,-x,color);
    }

      特性2代码如下:

      

        COLORREF color = RGB(0,0,0);
        double di = 0;
        int xi = 0,yi = R;
        DrawAxial(hdc,xi,yi,color);
        for(int i=1;i<=(int)(1.0*R/sqrt(2.0));++i)
        {
            di = (xi+1)*(xi+1) + (yi-0.5)*(yi-0.5) - R*R;
            ++xi;
            if(di >= 0)
            {
                --yi;
            }
            DrawAxial(hdc,xi,yi,color);
        }

      R为半径,起点为(0,R)。通过公式可以轻而易举地写出代码。

      完整win32代码如下:

      

    #include "Main.h"
    #include<tchar.h>
    #include<stdio.h>
    #include<windows.h>
    #include<math.h>
    
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        WNDCLASS wndcls;
        wndcls.cbClsExtra = 0;
        wndcls.cbWndExtra = 0;
        wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
        wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
        wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
        wndcls.hInstance = hInstance;
        wndcls.lpfnWndProc = WinSunProc;
        wndcls.lpszClassName = _T("sunxin2006");
        wndcls.lpszMenuName = NULL;
        wndcls.style = CS_HREDRAW | CS_VREDRAW;
        RegisterClass(&wndcls);
    
        HWND hwnd = CreateWindow(_T("sunxin2006"),_T("helloworld"),WS_OVERLAPPEDWINDOW,
            0,0,600,400,NULL,NULL,hInstance,NULL);
        ShowWindow(hwnd,SW_SHOW);
        UpdateWindow(hwnd);
    
        MSG msg;
        while(GetMessage(&msg,NULL,0,0)>0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
    VOID OnCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        int scrWidth,scrHeight;
        RECT rect;
        //获得屏幕尺寸
        scrWidth = GetSystemMetrics(SM_CXSCREEN);
        scrHeight = GetSystemMetrics(SM_CYSCREEN);
        //取得窗口尺寸
        GetWindowRect(hwnd,&rect);
        //重新设置rect里的值
        rect.left = (scrWidth-rect.right)/2;
        rect.top = (scrHeight-rect.bottom)/2;
        //移动窗口到指定的位置
        SetWindowPos(hwnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW);
    }
    
    VOID DrawAxial(HDC hdc,int x,int y,COLORREF color)
    {
        SetPixelV(hdc,x,y,color);
        SetPixelV(hdc,x,-y,color);
        SetPixelV(hdc,-x,y,color);
        SetPixelV(hdc,-x,-y,color);
        SetPixelV(hdc,y,x,color);
        SetPixelV(hdc,y,-x,color);
        SetPixelV(hdc,-y,x,color);
        SetPixelV(hdc,-y,-x,color);
    }
    
    
    VOID MyDrawCircle(HWND hwnd,HDC hdc,const POINT& pt,int R)
    {
        //Ellipse(hdc,pt.x-R/2,pt.y-R/2,pt.x+R/2,pt.y+R/2);
    
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        SIZE ptOldViewExt,ptOldWindowExt;
        POINT ptOldOrg;
        int OldMapMode = SetMapMode(hdc,MM_ANISOTROPIC);
        int iWidth = abs(rtClient.right - rtClient.left);
        int iHeight = abs(rtClient.bottom - rtClient.top);
        SetViewportExtEx(hdc,iWidth,iHeight,&ptOldViewExt);
        SetWindowExtEx(hdc,iWidth,-iHeight,&ptOldWindowExt);
        POINT ptOrg = {pt.x,pt.y};
        DPtoLP(hdc,&ptOrg,1);
        SetWindowOrgEx(hdc,-ptOrg.x,-ptOrg.y,&ptOldOrg);
    
        COLORREF color = RGB(0,0,0);
        double di = 0;
        int xi = 0,yi = R;
        DrawAxial(hdc,xi,yi,color);
        for(int i=1;i<=(int)(1.0*R/sqrt(2.0));++i)
        {
            di = (xi+1)*(xi+1) + (yi-0.5)*(yi-0.5) - R*R;
            ++xi;
            if(di >= 0)
            {
                --yi;
            }
            DrawAxial(hdc,xi,yi,color);
        }
    
        SetViewportExtEx(hdc,ptOldViewExt.cx,ptOldViewExt.cy,NULL);
        SetWindowExtEx(hdc,ptOldWindowExt.cx,ptOldWindowExt.cy,NULL);
        SetWindowOrgEx(hdc,ptOldOrg.x,ptOldOrg.y,NULL);
    
    }
    
    VOID MyDrawCircle(HWND hwnd,HDC hdc,int iLeft,int iTop,int iRight,int iBottom)
    {
        POINT  pt = {(iLeft+iRight)/2,(iTop+iBottom)/2};
        MyDrawCircle(hwnd,hdc,pt,abs(iRight-iLeft)/2);
    }
    
    VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd,&ps);
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hMemBmp = CreateCompatibleBitmap(hdc,rtClient.right,rtClient.bottom);
        HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC,hMemBmp);
        FillRect(hMemDC,&rtClient,WHITE_BRUSH);
    
        //POINT pt = {250,250};
        //MyDrawCircle(hwnd,hMemDC,pt,100);
        MyDrawCircle(hwnd,hMemDC,100,100,300,300);
        BitBlt(hdc,0,0,rtClient.right,rtClient.bottom,hMemDC,0,0,SRCCOPY);
        SelectObject(hMemDC,hOldBmp);
        DeleteObject(hMemBmp);
        EndPaint(hwnd,&ps);
    }
    
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_CREATE:
            OnCreate(hwnd,wParam,lParam);
            break;
        case WM_PAINT:
            OnPaint(hwnd,wParam,lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd,uMsg,wParam,lParam);
        }
        return 0;
    }
    View Code

     修改:全部代码这里的OnPaint函数中hMemDC忘记delelte了。。。

    椭圆的扫描转换(先贴代码)

    #include "Main.h"
    #include<tchar.h>
    #include<stdio.h>
    #include<windows.h>
    #include<math.h>
    
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        WNDCLASS wndcls;
        wndcls.cbClsExtra = 0;
        wndcls.cbWndExtra = 0;
        wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
        wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
        wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
        wndcls.hInstance = hInstance;
        wndcls.lpfnWndProc = WinSunProc;
        wndcls.lpszClassName = _T("sunxin2006");
        wndcls.lpszMenuName = NULL;
        wndcls.style = CS_HREDRAW | CS_VREDRAW;
        RegisterClass(&wndcls);
    
        HWND hwnd = CreateWindow(_T("sunxin2006"),_T("helloworld"),WS_OVERLAPPEDWINDOW,
            0,0,600,400,NULL,NULL,hInstance,NULL);
        ShowWindow(hwnd,SW_SHOW);
        UpdateWindow(hwnd);
    
        MSG msg;
        while(GetMessage(&msg,NULL,0,0)>0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
    VOID OnCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        int scrWidth,scrHeight;
        RECT rect;
        //获得屏幕尺寸
        scrWidth = GetSystemMetrics(SM_CXSCREEN);
        scrHeight = GetSystemMetrics(SM_CYSCREEN);
        //取得窗口尺寸
        GetWindowRect(hwnd,&rect);
        //重新设置rect里的值
        rect.left = (scrWidth-rect.right)/2;
        rect.top = (scrHeight-rect.bottom)/2;
        //移动窗口到指定的位置
        SetWindowPos(hwnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW);
    }
    
    VOID DrawAxial(HDC hdc,int x,int y,COLORREF color)
    {
        SetPixelV(hdc,x,y,color);
        SetPixelV(hdc,-x,y,color);
        SetPixelV(hdc,x,-y,color);
        SetPixelV(hdc,-x,-y,color);
    }
    
    VOID OnDrawElipse(HWND hwnd,HDC hdc,const POINT& pt,double a,double b)
    {
        //Ellipse(hdc,pt.x-a,pt.y-b,pt.x+a,pt.y+b);
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        int OldMapMode = SetMapMode(hdc,MM_ANISOTROPIC);
        SIZE OldViewExt,OldWindowExt;
        SetViewportExtEx(hdc,rtClient.right,rtClient.bottom,&OldViewExt);
        SetWindowExtEx(hdc,rtClient.right,-rtClient.bottom,&OldWindowExt);
        POINT OldOrg,ptOrg = {pt.x,pt.y};
        DPtoLP(hdc,&ptOrg,1);
        SetWindowOrgEx(hdc,-ptOrg.x,-ptOrg.y,&OldOrg);
    
    
        COLORREF color = RGB(0,0,0);
        int xi = 0,yi = b;
        int divison = a;
        if(a*a+b*b !=0)
        {
            divison = (int)(a*a/sqrt((a*a+b*b)));
        }
        DrawAxial(hdc,xi,yi,color);
        for(xi=1;xi<=divison;++xi)
        {
            double di = b*b*xi*xi+a*a*(yi-0.5)*(yi-0.5) - a*a*b*b;
            if(di >=0) --yi;
            DrawAxial(hdc,xi,yi,color);
        }
        --xi;
        for(;yi>=0;--yi)
        {
            double di = b*b*(xi+0.5)*(xi+0.5)+a*a*(yi-1)*(yi-1) - a*a*b*b;
            if(di < 0) ++xi;
            DrawAxial(hdc,xi,yi,color);
        }
        
        SetWindowOrgEx(hdc,OldOrg.x,OldOrg.y,NULL);
        SetWindowExtEx(hdc,OldWindowExt.cx,OldWindowExt.cy,NULL);
        SetViewportExtEx(hdc,OldViewExt.cx,OldViewExt.cy,NULL);
        SetMapMode(hdc,OldMapMode);
    }
    VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd,&ps);
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hMemBmp = CreateCompatibleBitmap(hMemDC,rtClient.right,rtClient.bottom);
        HBITMAP hOldBmp = (HBITMAP) SelectObject(hMemDC,hMemBmp);
        FillRect(hMemDC,&rtClient,WHITE_BRUSH);
    
        POINT pt = {200,200};
        OnDrawElipse(hwnd,hMemDC,pt,150,100);
    
        BitBlt(hdc,0,0,rtClient.right,rtClient.bottom,hMemDC,0,0,SRCCOPY);
        SelectObject(hMemDC,hOldBmp);
        DeleteObject(hMemDC);
        DeleteObject(hMemBmp);
        EndPaint(hwnd,&ps);
    }
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_CREATE:
            OnCreate(hwnd,wParam,lParam);
            break;
        case WM_PAINT:
            OnPaint(hwnd,wParam,lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd,uMsg,wParam,lParam);
        }
        return 0;
    }
    View Code

     椭圆可以分为4对称,x轴对称,y轴对称。在第一象限椭圆上点为(x,y),则对称点(x,-y),(-x,y),(-x,-y)。由于第一象限中y/x的值是有abs(k)>1到abs(k)<1或者相反。所以要先求得abs(k)=1的情况,然后根据该分界线分为两部分。

    求k=-1,其中的k为斜率。

      解:

        b^2*x^2 + a^2*y^2-a^2*b^2 = 0;

        对其求导 2*b*x + 2*a*y*y' = 0    =>   y1 = 1  =>  a^2*y = b^2*x

        带入椭圆方程求得(a^2/sqrt(a^2+b^2),b^2/sqrt(a^2+b^2))

           方程b^2*x^2 + a^2*y^2-a^2*b^2 = 0;

      当b<a时,如果a>b时,可以考虑一下。

      第一部分x在(0,a^2/sqrt(a^2+b^2))时:

        d1i = b^2*(xi+1)^2 +a^(yi-0.5)^2-a^y2b4*b^2;

        yi+1 = di>=0 ? yi-1 : yi;

        第二部分y在(b^2/sqrt(a^2+b^2))时:

        d2i = b^2*(xi+0.5)^2+a^2*(yi-1)^2 - a^2*b^2;

        xi+1 = d2i >= 0 ? xi:xi+1;

      直线扫描转换算法在处理非水平,非垂直,非45度的直线段时会出现锯齿,而画曲线更是如此!!!因此出现了反走样技术来抗锯齿。反走样技术主要分为两类:一类是硬件技术,通过提高显示器的分别率来实现,另一类是软件技术,通过改进算法来实现。软件反走样技术主要是加权区域采样。

       Wu反走样算法

      该算法是采取空间混色原理来对走样进行修正。空间混色原理指出,人眼对某一区域颜色的识别是取这个区域的平均值。Wu反走样算法原理是对于理想直线上的任意一点,同时以两个不同亮度等级的相邻像素来表示。

           推导公式:

        x^2+y^2 - R^2 = 0;

        y = sqrt(R^2-X^2);

        y0 = int(y),y1 = ceil(y);

        最后结论(x+1,y0,255*(y-y0)),(x+1,y1,255*(y-y1));第三个是颜色。

      代码:

      以下代码是画一个黑色圆圈,请把字体设成多字节然后编译。

    #include "Main.h"
    #include<tchar.h>
    #include<stdio.h>
    #include<windows.h>
    #include<math.h>
    
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        WNDCLASS wndcls;
        wndcls.cbClsExtra = 0;
        wndcls.cbWndExtra = 0;
        wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
        wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
        wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
        wndcls.hInstance = hInstance;
        wndcls.lpfnWndProc = WinSunProc;
        wndcls.lpszClassName = _T("sunxin2006");
        wndcls.lpszMenuName = NULL;
        wndcls.style = CS_HREDRAW | CS_VREDRAW;
        RegisterClass(&wndcls);
    
        HWND hwnd = CreateWindow(_T("sunxin2006"),_T("helloworld"),WS_OVERLAPPEDWINDOW,
            0,0,600,400,NULL,NULL,hInstance,NULL);
        ShowWindow(hwnd,SW_SHOW);
        UpdateWindow(hwnd);
    
        MSG msg;
        while(GetMessage(&msg,NULL,0,0)>0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
    VOID OnCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        int scrWidth,scrHeight;
        RECT rect;
        //获得屏幕尺寸
        scrWidth = GetSystemMetrics(SM_CXSCREEN);
        scrHeight = GetSystemMetrics(SM_CYSCREEN);
        //取得窗口尺寸
        GetWindowRect(hwnd,&rect);
        //重新设置rect里的值
        rect.left = (scrWidth-rect.right)/2;
        rect.top = (scrHeight-rect.bottom)/2;
        //移动窗口到指定的位置
        SetWindowPos(hwnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW);
    }
    
    
    VOID DrawAx(HDC hdc,int x,int y,COLORREF c)
    {
        SetPixelV(hdc,x,y,c);
        SetPixelV(hdc,-x,y,c);
        SetPixelV(hdc,x,-y,c);
        SetPixelV(hdc,-x,-y,c);
        SetPixelV(hdc,y,x,c);
        SetPixelV(hdc,y,-x,c);
        SetPixelV(hdc,-y,x,c);
        SetPixelV(hdc,-y,-x,c);
    }
    VOID DrawMyCircle(HWND hwnd,HDC hdc,WPARAM wParam,LPARAM lParam)
    {
        int R = 50;
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        POINT pt = {300,200};    //圆心
        Ellipse(hdc,pt.x-R,pt.y-R,pt.x+R,pt.y+R);
        pt.x = 100;
        int OldMapMode = SetMapMode(hdc,MM_ANISOTROPIC);
        SIZE OldViewSize,OldWindowSize;
        POINT ptOldOrg;
        SetViewportExtEx(hdc,rtClient.right,rtClient.bottom,&OldViewSize);
        SetWindowExtEx(hdc,rtClient.right,-rtClient.bottom,&OldWindowSize);
        DPtoLP(hdc,&pt,1);
        SetWindowOrgEx(hdc,-pt.x,-pt.y,&ptOldOrg);
    
        double x=0,y=R;
        DrawAx(hdc,0,R,RGB(0,0,0));
        for(x=1;x<=1.0*R/sqrt(2.0);++x)
        {
            y = sqrt(R*R-x*x);
            double y0 = int(y),y1 = ceil(y);
            int c0 = (int)(255.0*(y-y0)),c1 = (int)(255.0*(y1-y));
            DrawAx(hdc,x,y0,RGB(c0,c0,c0));
            DrawAx(hdc,x,y1,RGB(c1,c1,c1));
        }
    
    
        SetWindowOrgEx(hdc,ptOldOrg.x,ptOldOrg.y,NULL);
        SetWindowExtEx(hdc,OldWindowSize.cx,OldWindowSize.cy,NULL);
        SetViewportExtEx(hdc,OldViewSize.cx,OldViewSize.cy,NULL);
        SetMapMode(hdc,OldMapMode);
    }
    VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd,&ps);
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc,rtClient.right,rtClient.bottom);
        SelectObject(hMemDC,hBitmap);
        FillRect(hMemDC,&rtClient,WHITE_BRUSH);
    
        DrawMyCircle(hwnd,hMemDC,wParam,lParam);
    
        BitBlt(hdc,0,0,rtClient.right,rtClient.bottom,hMemDC,0,0,SRCCOPY);
        DeleteObject(hBitmap);
        DeleteObject(hMemDC);
        EndPaint(hwnd,&ps);
    }
    LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_PAINT:
            OnPaint(hwnd,wParam,lParam);
            break;
        case WM_CREATE:
            OnCreate(hwnd,wParam,lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd,uMsg,wParam,lParam);
        }
        return 0;
    }
    View Code

      第一个圆是经过反走样处理的,第二个圆是未处理过的。

      彩色反走样就是线条颜色到背景颜色的渐变过程,假设线段颜色为(rf,gf,bf),背景色(rb,gb,bb),则像素颜色为RGB((rb-rf)*ei,(gb-gf)*ei,(bb-bf)*ei+bi);

  • 相关阅读:
    网页打开qq
    正则表达式
    微信小程序 如何使用globalData
    微信小程序中常见的typeof cb == “function” && cb(that.globalData.userInfo)
    MongoDB
    Elasticsearch学习
    Kafka学习之路 (一)Kafka的简介
    mybatis sql语句中转义字符
    定时任务
    mybatis insert into 返回id,useGeneratedKeys,keyColumn,keyProperty,parameterType
  • 原文地址:https://www.cnblogs.com/jlyg/p/8446862.html
Copyright © 2011-2022 走看看