Boost的動態多維陣列-multi_array
阿新 • • 發佈:2018-12-30
簡短的例子
- #include "boost/multi_array.hpp"
- #include <cassert>
- int main () {
- // 建立一個 3 x 4 x 2 的 3D 陣列
- typedef boost::multi_array<double, 3> array_type;
- typedef array_type::index index;
- array_type myarray(boost::extents[3][4][2]);
- // 賦值到陣列的元素
-
int values = 0;
- for(index i = 0; i != 3; ++i)
- for(index j = 0; j != 4; ++j)
- for(index k = 0; k != 2; ++k)
- myarray[i][j][k] = values++;
- // 校驗元素值
- int verify = 0;
- for(index i = 0; i != 3; ++i)
- for(index j = 0; j != 4; ++j)
- for(index k = 0; k != 2; ++k)
-
assert(myarray[i][j][k] == verify++);
- return 0;
- }
- boost::multi_array是一個模板類,第一個模板引數指定元素資料型別;第二個模板引數是一個數值,指出陣列維度。
- multi_array::index型別定義用於描述資料索引,一般來說它就是int
- boost:: extents的連續多個[]操作用於指明每個維度的大小(另外,也可以使用boost::array來指明維度大小,如boost:: array<int,3> dims={3,4,2}; array_type myarray(dims);)
- boost::multi_array的讀寫介面和原生多維陣列相同
把連續記憶體適配成多維陣列
- /* 原來的程式碼
- typedef boost::multi_array<double, 3> array_type;
- typedef array_type::index index;
- array_type myarray(boost::extents[3][4][2]);
- */
- typedef boost::multi_array_ref<double, 3> array_type;
- typedef array_type::index index;
- double buf[24]; //連續記憶體塊
- array_type myarray(buf, boost::extents[3][4][2]); //把buf適配成3 x 4 x 2 的3D陣列
- ...
-
Boost.MultiArray是一個動態多維陣列庫。它實現了一個通用、與標準庫的容器一致的介面,並且具有與C++中內建的多維陣列一樣的介面和行為。
子檢視
- ...
- typedef array_type::index_range range;
- array_type::array_view<3>::type myview =
- myarray[ boost::indices[range(1,3)][range(0,4,2)][range(0,2)] ];
- for (array_type::index i = 0; i != 2; ++i)
- for (array_type::index j = 0; j != 2; ++j)
- for (array_type::index k = 0; k != 2; ++k)
- assert(myview[i][j][k] == myarray[i+1][j*2][k]);
- multi_array的子檢視型別由它的array_view::type型別定義確定,這個array_view是個模板類,其引數指定了檢視的維度。
- multi_array的[]操作除了接受整數來模擬原生陣列以外,還接受boost::indices物件的[]操作所返回的東東(這個東東是index_gen型別,我們只管用,不予深究),向multi_array的[]操作傳入這個東東可以得到一個子檢視。
- multi_array有個index_range型別,用於指定索引的起始、終止和步進值(預設是1)。boost::indices物件的[]操作接受這個型別的資料才能生成指定區域的子檢視。
- 子檢視的用法和多維陣列一樣
- ...
- typedef array_type::index_range range;
- array_type::array_view<2>::type myview =
- myarray[ boost::indices[range(1,3)][range(0,4,2)][1] ];
- for (array_type::index i = 0; i != 2; ++i)
- for (array_type::index j = 0; j != 2; ++j)
- assert(myview[i][j] == myarray[i+1][j*2][1]);
-
儲存的順序
- typedef boost::multi_array<double,3> array_type;
- array_type A(boost::extents[3][4][2],boost::fortran_storage_order);
- call_fortran_function(A.data());
- typedef boost::general_storage_order<3> storage;
- typedef boost::multi_array<int,3> array_type;
- // 先儲存最後一個維度,然後是第一個維度,最後是中間
- array_type::size_type ordering[] = {2,0,1};
- // 以降序儲存第一個維度(維度0)
- bool ascending[] = {false,true,true};
-
array_type A(extents[3][4][2],storage(ordering,ascending));
改變陣列的形狀
- ...
- boost::array<int,3> dims = {2, 3, 4};
- myarray.reshape( dims );
- //現在myarray是2x3x4的陣列了
改變陣列的大小
- myarray.resize(boost::extents[1][2][3]);
-
使用multi_array做影象格式轉換
AGG的內部格式是 color buf[y][x][v]
CImg的內部格式是 color buf[v][y][x]
其中color為單通道顏色值、v代表顏色通道(如RGB三色)、x,y是座標。我們這裡讓CImg的z軸為1,即二維影象。- #include "boost/multi_array.hpp" // multi_array
- #include "cimg.h" // CImg
- #include <agg_pixfmt_rgb.h> //後面全是AGG的
- #include <agg_scanline_u.h>
- #include <agg_renderer_scanline.h>
- #include <../font_win32_tt/agg_font_win32_tt.h>
- #include <agg_font_cache_manager.h>
- #include <agg_conv_bspline.h>
- #include <agg_path_storage.h>
- #include <agg_conv_curve.h>
- #include <agg_conv_transform.h>
- #include <agg_ellipse.h>
- #include <agg_trans_single_path.h>
- using cimg_library::CImg;
- int main () {
- // AGG畫圖,寫了一行字
- char buf[200][300][3];
- agg::rendering_buffer rbuf(
- (unsigned char*)buf,
- 300, 200,
- 300*3);
- agg::pixfmt_rgb24 pixf(rbuf);
- agg::renderer_base<agg::pixfmt_rgb24> renb(pixf);
- typedef agg::font_engine_win32_tt_int16 fe_type;
- typedef agg::font_cache_manager<fe_type> fcman_type;
- renb.clear(agg::rgba(0.5,0.5,1));
- fe_type font(::GetDC(0));
- fcman_type font_manager(font);
- font.height(32.0);
- font.flip_y(true);
- font.hinting(true);
- if(!font.create_font("Comic Sans MS",agg::glyph_ren_outline)) return -1;
- //座標轉換管道
- typedef agg::conv_curve<
- fcman_type::path_adaptor_type
- > cc_pa_type;
- cc_pa_type ccpath(font_manager.path_adaptor());
- typedef agg::conv_transform<cc_pa_type,
- agg::trans_single_path> ct_cc_pa_type;
- agg::trans_single_path trans_path;
- ct_cc_pa_type ctpath(ccpath, trans_path);
- agg::path_storage ps;
- ps.move_to(20,100);
- ps.line_rel(80,50);
- ps.line_rel(100,-100);
- ps.line_rel(100,100);
- agg::conv_bspline<agg::path_storage> cb_ps(ps);
- trans_path.add_path(cb_ps);
- agg::rasterizer_scanline_aa<> ras;
- agg::scanline_u8 sl;
- double x=0, y=0;
- for(const wchar_t *p = L"http://www.cpp-prog.com"; *p; p++)
- {
- const agg::glyph_cache* gc = font_manager.glyph(*p);
- if(gc)
- {
- font_manager.init_embedded_adaptors(gc, x, y);
- ras.add_path(ctpath);
- x += gc->advance_x;
- y += gc->advance_y;
- }
- }
- agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba(1,0,0));
- // 定義CImg
- CImg<unsigned char> img(300,200,1,3);
- // 用multi_array把AGG影象資料轉成CImg
- typedef boost::multi_array_ref<unsigned char,3> array_type;
- // AGG->多維陣列
- /**
- * AGG排列是[y][x][v], CImg是[v][y][x]
- * 設y=2, x=1, v=0(C語言預設順序)
- * 則AGG的[2][1][0]對應CImg就是[0][2][1]
- */
- typedef boost::general_storage_order<3> storage;
- array_type::size_type ordering[] = {0,2,1};
- bool ascending[] = {true,true,true};
- array_type array_agg((unsigned char*)buf,boost::extents[3][200][300],storage(ordering,ascending));
- // 把AGG影象資料賦值給CImg,multi_array_ref內部做轉換工作
- array_type(img.data, boost::extents[3][200][300]) = array_agg;
- // CImg影象處理
- img.blur(6).noise(10).erode(4);
- // 把CImg處理過的影象又傳給AGG
- array_agg = array_type(img.data, boost::extents[3][200][300]);
- // AGG在此基礎上畫圖
- agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba(1,1,0));
- // 給CImg顯示
- array_type(img.data, boost::extents[3][200][300]) = array_agg;
- img.erode(2);
- img.display("view");
- return 0;
- }