在C ++运行时将1D数组(指针)作为3D矩阵处理

时间:2017-11-13 15:37:36

标签: c++ arrays multidimensional-array

我收到一些图像数据unsigned char *image = load_image(…);

此数据是一个3D矩阵:x(字符),y(字符)和channel (RGB)(字符)。

如何通过重载image[x][y][channel][]的形式访问每个元素?例如。第999行,第10000列,绿色通道:image[999][10000][1]

澄清:

  1. 我想使用C多维数组语法:array[x][y][z],而不是array[x * height * channels + y * channels + z]

  2. 我可以将1D数组作为2D数组访问:

    unsigned char (*imageMatrix)[height] = (unsigned char (*)[height])image
    imageMatrix[x][y] = 100
    
  3. I already asked如何在纯C中完成。在这里,我想知道如何在C ++中更好地实现它。

2 个答案:

答案 0 :(得分:3)

您可以使用可获得所需内容的功能创建Image课程

class Image {
    int imgSize;
    char * img;

public:
    Image(): imgSize(0), img(nullptr) {}
    Image(char* image, int size): imgSize(size), img(image) {}

    char getPixel(int x, int y, int z) {
        if(x < imgSize && y < imgSize && z < imgSize) {
            return img[x * imgSize * imgSize + y * imgSize + z];
        } else {
            // Error
        }
    }

    char operator(int x, int y, int z) {
        // The same as getPixel
    }
}

getPixel在我看来是最好的方法,因为无论何时你打电话,你(以及使用你的代码的人)都会知道你的名字是什么(即使在6个月后你会立即认识你)得到一个像素)。重载operator()也是一种很好的方法,但我不会用它来引起混淆或不需要的行为。两者都隐藏了类的内部结构,不需要任何代理类。

重载operator[]是一个选项,但为了支持[][][]之类的链接,您需要代理类,如果设计不正确,将严重影响代码的性能。

您可以阅读C++ FAQ了解详情。

答案 1 :(得分:0)

  

如何通过重载image[x][y][channel]

将每个元素作为[]进行访问

当您为图像类重载数组运算符时,它只能在其接口中支持语法image[x]

为了能够支持image[x][y]image[x]需要返回一个对象或对需要支持数组运算符的对象的引用。

为了能够支持image[x][y][z]image[x][y]需要返回一个对象或对需要支持数组运算符的对象的引用。

这是一个演示如何完成的示例程序。

免责声明请注意,这不是生产就绪代码。

#include <iostream>
#include <cassert>

struct Image
{
   Image(unsigned int x,
         unsigned int y,
         unsigned int z) : x_(x), y_(y), z_(z), data(new unsigned char [x*y*z]) {}

   // Need appropriate copy constructor and destructor.

   // Helper classes to support the 3D array operator syntax.

   struct image_2
   {
      image_2(Image& im, unsigned i, unsigned j) : im_(im), i_(i), j_(j) {}
      unsigned char& operator[](unsigned k)
      {
         assert( k < im_.z_ );
         unsigned int index = i_*im_.y_*im_.z_ + j_*im_.z_ + k;
         return im_.data[index];
      }

      Image& im_;
      unsigned int i_;
      unsigned int j_;
   };

   struct image_1
   {
      image_1(Image& im, unsigned i) : im_(im), i_(i) {}

      image_2 operator[](unsigned int j)
      {
         assert( j < im_.y_ );
         return image_2(im_, i_, j);
      }

      Image& im_;
      unsigned int i_;
   };

   // The toplevel array operator
   image_1 operator[](unsigned i)
   {
      assert( i < x_ );
      return image_1(*this, i);
   }

   unsigned x_;
   unsigned y_;
   unsigned z_;
   unsigned char* data;
};

int main()
{
   unsigned int x = 5;
   unsigned int y = 5;
   unsigned int z = 3;
   Image im(5, 5, 3);

   for ( unsigned int i = 0; i < x; ++i )
   {
      for ( unsigned int j = 0; j < y; ++j )
      {
         for ( unsigned int k = 0; k < z; ++k )
         {
            // Set some arbitrary value
            im[i][j][k] = (i+1) + (j+1)*5 + (k+1)*5;

            // Get the value
            std::cout << (int)im[i][j][k] << " ";
         }
         std::cout << std::endl;
      }
   }
}

输出:

11 16 21
16 21 26
21 26 31
26 31 36
31 36 41
12 17 22
17 22 27
22 27 32
27 32 37
32 37 42
13 18 23
18 23 28
23 28 33
28 33 38
33 38 43
14 19 24
19 24 29
24 29 34
29 34 39
34 39 44
15 20 25
20 25 30
25 30 35
30 35 40
35 40 45