天天看點

(轉)用AGG實作高品質圖形輸出(一) - CoolJie

(轉)用AGG實作高品質圖形輸出(一)

2011-04-27 09:38 

CoolJie 

閱讀(1943) 

評論(3) 

編輯 

收藏 

舉報

AGG是一個開源、高效的跨平台2D圖形庫。AGG的功能與GDI+的功能非常類似,但提供了比GDI+更靈活的程式設計接口,其産生的圖形的品質也非常高(自稱超過GDI+)

使用前AGG的準備工作

  1. 下載下傳AGG庫,它的家在http://www.antigrain.com,目前最高版本是AGG2.5
  2. 解壓,後面以[AGG]表示AGG的解壓目錄.
  3. 把[AGG]\include加入到include搜尋目錄中
  4. 把[AGG]\src裡所有cpp加入到項目中(或者用makefile一起編譯)
  5. 另外,AGG還有一些其它元件,用到時也要把它們(都是些.h和.cpp檔案)加入項目:
    • 如果要用AGG的控件和窗體,要加入[AGG]\src\ctrl\*.cpp和[AGG]\src\platform\<OS>\*.cpp,頭檔案在[AGG]\include\ctrl和[AGG]\include\platform裡
    • 如果要用到TrueType字型顯示,要加入[AGG]\font_win32_tt目錄下的源碼和頭檔案。利用freetype庫,則是[AGG]\font_freetype目錄。
    • 如果要用到Generic Polygon Clipper庫(一個區域剪裁計算庫),加入[AGG]\gpc目錄下的源碼和頭檔案。
AGG圖形顯示原理見下圖:
(轉)用AGG實作高品質圖形輸出(一) - CoolJie

其中:

  1. Vertex Source 頂點源,裡面存放了一堆2D頂點以及對應的指令,如"MoveTo"、"LineTo"等。
  2. Coordinate conversion pipeline 坐标轉換管道,它可以變換Vertex Source中的頂點,比如矩陣變換,輪廓提取,轉換為虛線等。
  3. Scanline Rasterizer 把頂點資料(矢量資料)轉換成一組水準掃描線,掃描線由一組線段(Span)組成,線段(Span)包含了起始位置、長度和覆寫率(可以了解為透明度)資訊。AGG的抗鋸齒(Anti-Aliasing)功能也是在這時引入的。
  4. Renderers 渲染器,渲染掃描線(Scanline)中的線段(Span),最簡單的就是為Span提供單一顔色,複雜的有多種顔色(如漸變)、使用圖像資料、Pattern等。
  5. Rendering Buffer 用于存放像素點陣資料的記憶體塊,這裡是最終形成的圖像資料。

要了解AGG的工作原理,先看一段代碼:

#include "agg_basics.h"
    #include "agg_rendering_buffer.h"
    #include "agg_rasterizer_scanline_aa.h"
    #include "agg_scanline_u.h"
    #include "agg_renderer_scanline.h"
    #include "agg_pixfmt_rgb.h"
    #include "platform/agg_platform_support.h"
    #include "agg_ellipse.h"
    #include "agg_conv_contour.h"
    #include "agg_conv_stroke.h"
     
    class the_application : public agg::platform_support
    {
    public:
        the_application(agg::pix_format_e format, bool flip_y) :
            agg::platform_support(format, flip_y)
        {
        }
     
        virtual void on_draw()
        {
            //Rendering Buffer
            agg::rendering_buffer &rbuf = rbuf_window();
            agg::pixfmt_bgr24 pixf(rbuf);
           
            // Renderers
            typedef agg::renderer_base renderer_base_type;
            renderer_base_type renb(pixf);
     
            typedef agg::renderer_scanline_aa_solid renderer_scanline_type;
            renderer_scanline_type rensl(renb);
           
            // Vertex Source
            agg::ellipse ell(100,100,50,50);
           
            // Coordinate conversion pipeline
            typedef agg::conv_contour ell_cc_type;
            ell_cc_type ccell(ell);
           
            typedef agg::conv_stroke ell_cc_cs_type;
            ell_cc_cs_type csccell(ccell);
           
            // Scanline Rasterizer
            agg::rasterizer_scanline_aa<> ras;
            agg::scanline_u8 sl;
           
            // Draw
            renb.clear(agg::rgba8(255,255,255));
            for(int i=0; i<5; i++)
            {
                ccell.width(i*20);
                ras.add_path(csccell);
                rensl.color( agg::rgba8(0,0,i*50));
                agg::render_scanlines(ras,sl,rensl);
            }
        }
    };
     
    int agg_main(int argc, char* argv[])
    {
        the_application app(agg::pix_format_bgr24, false);
        app.caption("AGG Example. Anti-Aliasing Demo");
     
        if(app.init(600, 400, agg::window_resize))
        {
            return app.run();
        }
        return -1;
    }      

編譯這段代碼的方法是(以VC為例):

  1. 建立空白GUI項目(就是有WinMain的項目)
  2. 把[AGG]\src裡所有*.cpp加入到項目中
  3. 把[AGG]\src\platform\Win32\*.cpp加入到項目中
  4. Ctrl+C/Ctrl+V 上面的代碼
  5. 編譯!

顯示效果:

(轉)用AGG實作高品質圖形輸出(一) - CoolJie

我們先不管agg_main及agg::platform_support的問題,實際上agg::platform_support隻是AGG給我們友善顯示AGG圖形用的,真正應用時幾乎不會用到(後面會講到怎樣把AGG圖形畫到HDC上)。

現在我們隻需要知道這個架構可以生成一個窗體,當窗體重畫時會調用virtual void on_draw()就行了。

現在直接從on_draw()開始看

  1. 通過rbuf_window()方法得到一個agg::rendering_buffer,它就是“Rendering Buffer”,是一塊用于存放圖像的記憶體塊。通過pixfmt_bgr24包裝,我們就可以以像素為機關存取圖像。
  2. agg::renderer_base和agg::renderer_scanline_aa_solid都屬于"渲染器Renderer"。renderer_base為底層渲染器,它支撐起所有的高層渲染器。這裡的renderer_scanline_aa_solid就是一個高層渲染器。
  3. agg::ellipse是“頂點源Vertex Source”,這個頂點源呈現的是一個圓形。
  4. agg::conv_contour和agg::conv_stroke作為“坐标轉換管道Coordinate conversion pipeline”,conv_contour擴充輪廓線,conv_stroke隻顯示輪廓線(如果沒有conv_stroke就會顯示實心圓,可以去掉試試)。
  5. agg::rasterizer_scanline_aa<>就是“Scanline Rasterizer”啦。
  6. agg::render_scanlines函數執行這個AGG工作流程。

轉自:http://www.cppprog.com/2009/0816/146.html

(轉)用AGG實作高品質圖形輸出(一) - CoolJie