我在c#中有一个3D数组的字节,我从一个位图中读取:
byte[w,h,3]
将这个数组重新整形成2D(线性)形式最简单和更具性能友好的方法是什么?
byte[w*h,3]
换句话说,我想保持通道数量(特征),但是以线形(而不是正方形)
让我试着说明输入和想要的输出:
输入:
|(r1,g1,b1) (r2,g2,b2) (r3,g3,b3)| |(r4,g4,b4) (r5,g5,b5) (r6,g6,b6)| |(r7,g7,b7) (r8,g8,b8) (r9,g9,b9)|
注意arr [0,0] = r1,arr [0,1] = g1,2] = b1等.
并输出:
|(r1,b3) (r4,b6) ...|
解决方法
这似乎工作正常,因为阵列已经在内存中正确的形状:
var a = new byte[2,2,2] { { { 1,2 },{ 3,4 } },{ { 5,6 },{ 7,8 } } }; var b = new byte[2 * 2,2]; //sizeof(byte) is obvIoUsly 1 here,but I put it there for documentation Buffer.BlockCopy(a,b,a.Length * sizeof(byte));
对于那些感兴趣的人:至于如果你真的想把2D数组转换成1D,该怎么办
byte[,] a = { {1,2},{3,4},{5,6},}; var b = new byte[a.GetLength(1) * a.GetLength(0)]; //Transpose const int R_STRIDE1 = 8; //Tune this for your cpu const int C_STRIDE1 = 8; //Tune this for your cpu //You should hoist the calls to GetLength() out of the loop unlike what I do here for (int r1 = 0; r1 < a.GetLength(0); r1 += R_STRIDE1) for (int c1 = 0; c1 < a.GetLength(1); c1 += C_STRIDE1) for (int r2 = 0; r2 < R_STRIDE1; r2++) for (int c2 = 0; c2 < C_STRIDE1; c2++) { var r = r1 + r2; var c = c1 + c2; if (r < a.GetLength(0) && c < a.GetLength(1)) b[c * a.GetLength(0) + r] = a[r,c]; }
这应该利用cpu中的缓存.我只做了有限的测试 – 这可能还是很慢的.尝试调整它,如果是.您可以(有点不平凡地)将其扩展到3D阵列.