用于从RGB值数组中切割平面(就地)的算法

我有一个平坦的字节RGB值数组,它们是R1 G1 B1 R2 G2 B2 R3 G3 B3 ... Rn Gn Bn 。 所以我的数据看起来像:

 char imageData[WIDTH * HEIGHT * 3]; 

但我想将WIDTH * HEIGHT数组传递给现有的C库,该C库需要这个数据的单个平面。 这将只是R值(或只是G,或只是B)的序列。

分配新数组并复制数据(duh)很容易。 但是图像非常大。 如果它不是一个C库,而是采用某种迭代接口来精细化“切片”遍历,那就太棒了。 但是我无法编辑我正在调用的代码……它需要一个指向顺序内存块的普通旧指针。

但是我有对这个数组的写访问权限。 创建一个将其分类为彩色平面的例程是可行的。 我还需要一个可以反转的反向转换,但根据定义,将它分类为平面的相同方法可以应用于取消它。

我能够(到位)将这个arrays转换为R1 R2 R3 ... Rn G1 G2 G3 ... Gn B1 B2 B3 ... Bn然后再返回? 任何非天真的算法?

如果你只需要一架飞机,这似乎很容易。 如果你需要全部3,你可能会有更复杂的算法运气。

 void PlanarizeR(char * imageData, int width, int height) { char *in = imageData; int pixelCount = width * height; for (int i = 0; i < pixelCount; ++i, in+=3) std::swap(*in, imageData[i]) } 

从高到低向后运行循环以反转过程应该不会太难。

本文“一种简单的In-Shuffle就地算法”描述了如何转置2 * N的矩阵,并给出了如何在其他情况下进行的提示,因此3 * N也是可能的。 这个对其他问题的回答表明它确实是可能的。

或者使用一种算法将每个值写入其转置位置,然后对该位置的值执行相同的操作,依此类推,直到连接循环。 在位向量中标记处理的值。 并继续,直到这个向量全是1。

两种算法都不是缓存友好的。 可能一些巧妙使用PREFETCH指令可以改善这一点。

编辑:

C ++,RGB到单平面,未优化:

 #include  #include  #include  enum {N = 8}; void transpose(std::vector& a) { std::bitset<3*N> b; for (int i = 1; i < 3*N; ++i) { if (b[i]) continue; int ptr = i; int next; char nextVal = a[i]; do { next = ptr/3 + N*(ptr%3); char prevVal = nextVal; nextVal = a[next]; a[next] = prevVal; ptr = next; b[ptr] = true; } while (ptr != i); } } int main() { std::vector a(3*N); for (int i = 0; i != 3*N; ++i) a[i] = i; transpose(a); for (int i = 0; i != 3*N; ++i) std::cout << (int)a[i] << std::endl; return 0; } 

我的初衷是使用大小为WIDTH HEIGHT的位向量,这会产生WIDTH HEIGHT / 8的开销 。 但是总是有可能牺牲空间的速度。 位向量可以是大小WIDTH或HEIGHT或任何期望值,甚至是0.技巧是保持指向单元的指针,在此之前所有值都被转置。 位向量用于单元格,从该指针开始。 在它全部为1之后,它移动到下一个位置,然后执行除实际数据移动之外的所有算法步骤。 并且位向量已准备好继续转置。 该变体是O(N ^ 2)而不是O(N)。

EDIT2:

PREFITCH优化并不难实现:只需计算索引,调用PREFETCH,并将索引放入队列(ringbuffer),然后从队列中获取索引并移动数据。

EDIT3:

其他算法的概念,即O(1)大小,O(N * log(N))时间,是缓存友好的并且可能比“循环”算法更快(对于图像大小<1Gb):

  • 将N * 3矩阵拆分为几个3 * 3的char矩阵并转置它们
  • 将结果拆分为char [3]的3 * 3矩阵并转置它们
  • 矩阵大小小于数组大小时继续
  • 现在我们有最多3 * 2 * log3(N)的订购件。 加入他们。
  • 首先加入相同大小的部分。 可以使用长度为4的非常简单的“循环”。
  • 用反向加入不等大小的部分(反向(a),反向(b))
 char *imageData = malloc (WIDTH * HEIGHT * 3 * sizeof(char)); 

此function执行此操作R1 R2 R3 … Rn G1 G2 G3 … Gn B1 B2 B3 … Bn ,,

 char *toRGB(char *imageData, int WIDTH, int HEIGHT){ int len = WIDTH * HEIGHT; char *RGB = malloc (len * sizeof(char)); int i, j = 0,flag = 0; for(i=0 ; i<=len ; i++, j+=3){ if(j