動態多維數組-multi_array

本站有AGGCImg 的圖像處理教程,AGG庫傾向於矢量繪圖,CImg傾向於圖像處理。我們可以考慮雙劍合壁,共同來生成我們要的圖像。可是它們的內部數據格式卻不完全相同:
  1. AGG的內部格式是 color buf[y][x][v]
    CImg的內部格式是 color buf[v][y][x]
    其中color爲單通道顏色值、v代表顏色通道(如RGB三色)、x,y是座標。我們這裏讓CImg的z軸爲1,即二維圖像。
  2. 我們得找個方法可以方便地互相轉換,這裏我們選用multi_array來做這件事(另,GIL也是一個不錯的候選方案,見本站GIL教程 )。
  3. #include "boost/multi_array.hpp" // multi_array
  4. #include "cimg.h" // CImg
  5. #include <agg_pixfmt_rgb.h> //後面全是AGG的
  6. #include <agg_scanline_u.h>
  7. #include <agg_renderer_scanline.h>
  8. #include <../font_win32_tt/agg_font_win32_tt.h>
  9. #include <agg_font_cache_manager.h>
  10. #include <agg_conv_bspline.h>
  11. #include <agg_path_storage.h>
  12. #include <agg_conv_curve.h>
  13. #include <agg_conv_transform.h>
  14. #include <agg_ellipse.h>
  15. #include <agg_trans_single_path.h>
  16.  
  17. using  cimg_library::CImg;
  18. int  main () {
  19.     // AGG畫圖,寫了一行字
  20.     char  buf[200][300][3];
  21.     agg::rendering_buffer rbuf(
  22.             (unsigned char *)buf,
  23.             300, 200,
  24.             300*3);
  25.     agg::pixfmt_rgb24 pixf(rbuf);
  26.     agg::renderer_base<agg::pixfmt_rgb24> renb(pixf);
  27.  
  28.     typedef  agg::font_engine_win32_tt_int16 fe_type;
  29.     typedef  agg::font_cache_manager<fe_type> fcman_type;
  30.  
  31.     renb.clear(agg::rgba(0.5,0.5,1));
  32.     fe_type font(::GetDC(0));
  33.     fcman_type font_manager(font);
  34.     font.height(32.0);
  35.     font.flip_y(true );
  36.     font.hinting(true );
  37.     if (!font.create_font( "Comic Sans MS" ,agg::glyph_ren_outline))  return  -1;
  38.     //座標轉換管道
  39.     typedef  agg::conv_curve<
  40.         fcman_type::path_adaptor_type
  41.     > cc_pa_type;
  42.     cc_pa_type ccpath(font_manager.path_adaptor());
  43.  
  44.     typedef  agg::conv_transform<cc_pa_type,
  45.         agg::trans_single_path> ct_cc_pa_type;
  46.     agg::trans_single_path trans_path;
  47.     ct_cc_pa_type ctpath(ccpath, trans_path);
  48.     
  49.     agg::path_storage ps;
  50.     ps.move_to(20,100);
  51.     ps.line_rel(80,50);
  52.     ps.line_rel(100,-100);
  53.     ps.line_rel(100,100);
  54.     
  55.     agg::conv_bspline<agg::path_storage> cb_ps(ps);
  56.     trans_path.add_path(cb_ps);
  57.  
  58.     agg::rasterizer_scanline_aa<> ras;
  59.     agg::scanline_u8 sl;
  60.     
  61.     double  x=0, y=0;
  62.     for ( const   wchar_t  *p = L "http://www.cppprog.com" ; *p; p++)
  63.     {
  64.         const  agg::glyph_cache* gc = font_manager.glyph(*p);
  65.         if (gc)
  66.         {
  67.             font_manager.init_embedded_adaptors(gc, x, y);
  68.             ras.add_path(ctpath);
  69.  
  70.             x += gc->advance_x;
  71.             y += gc->advance_y;
  72.         }
  73.     }
  74.     agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba(1,0,0));
  75.  
  76.     // 定義CImg
  77.     CImg<unsigned char > img(300,200,1,3);
  78.  
  79.     // 用multi_array把AGG圖像數據轉成CImg
  80.     typedef  boost::multi_array_ref<unsigned  char ,3> array_type;
  81.     // AGG->多維數組
  82.     /**
  83.     * AGG排列是[y][x][v], CImg是[v][y][x]
  84.     * 設y=2, x=1, v=0(C語言默認順序)
  85.     * 則AGG的[2][1][0]對應CImg就是[0][2][1]
  86.     */
  87.     typedef  boost::general_storage_order<3> storage;
  88.     array_type::size_type ordering[] = {0,2,1};
  89.     bool  ascending[] = { true , true , true };
  90.     array_type array_agg((unsigned char *)buf,boost::extents[3][200][300],storage(ordering,ascending));
  91.     // 把AGG圖像數據賦值給CImg,multi_array_ref內部做轉換工作
  92.     array_type(img.data, boost::extents[3][200][300]) = array_agg;
  93.  
  94.     // CImg圖像處理
  95.     img.blur(6).noise(10).erode(4);
  96.  
  97.     // 把CImg處理過的圖像又傳給AGG
  98.     array_agg = array_type(img.data, boost::extents[3][200][300]);
  99.  
  100.     // AGG在此基礎上畫圖
  101.     agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba(1,1,0));
  102.  
  103.     // 給CImg顯示
  104.     array_type(img.data, boost::extents[3][200][300]) = array_agg;
  105.     img.erode(2);
  106.     img.display("view" );  
  107.     return  0;
  108. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章