Boost.MultiArray是一个动态多维数组库。它实现了一个通用、与标准库的容器一致的接口,并且具有与C++中内建的多维数组一样的接口和行为。
简短的例子
- #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