C ++ RGB图像数据叠加到2D数组(向量矢量)

时间:2018-05-24 09:16:45

标签: c++ image-processing vector rgb

给定图像数据如何将RGB值叠加到矢量矢量上。从下面的代码;我有一个类型uint8_t的数组代表图像,然后我  reinterpret_cast将3字节映射到RGB结构,并通过for循环将它们放入2D数组中。

这是有效的(在屏幕截图下方),但感觉“笨拙”,有没有其他方法可以达到同样的效果? (可能是通过矢量向量,copy_n或类似的迭代器)

enter image description here

#include<vector>


struct RGB {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
};


int main() {
    std::vector<std::vector<RGB>> data;
    uint8_t height, width, idx = 0, jdx = 0;

    // data array representing image data - this would really be a bin fle
    //                    header         r,    g,    b        r,    g,    b      r,    g,    b        r,    g,    b       r,    g,    b       r,    g,    b      footer
    uint8_t temp[22] = { 0x02, 0x03,    0x01, 0x02, 0x03,   0x04, 0x05, 0x06,   0x07, 0xef, 0x05,   0x0a, 0x01, 0x02,   0x0d, 0xfe, 0x00,   0x10, 0xff, 0xff,   0xef, 0xef };

    // resize data vector based on (h,w) which we get from header info
    height = temp[0];
    width = temp[1];
    data.resize(height, std::vector<RGB>(width));

    // populate the 2D data of RGB values
    for (uint8_t i = 0; i<6; i++) {
        jdx = i % width;
        data[idx][jdx] = *(reinterpret_cast<RGB*>(&temp[(2 + (i*3))]));

        if (jdx == height)
            idx++;
    }

    return 0;
}

1 个答案:

答案 0 :(得分:1)

  1. 恕我直言,vector<vector< >>是合适的,如果行可能有不同的长度,但这样的东西实际上不再称为矩阵。 (OP样本的原始数据形成一个按行存储的矩阵。)

  2. 为什么有必要将temp数组复制到vector<>?这是重复数据。如果可以授予终身时间,则可以直接访问temp。 (否则,可以将其复制到vector<uint8_t>。)

  3. AFAIK,未授予struct RGB中组件的包装。因此,reinterpret_cast<RGB*>()不是访问字节的最简洁方法。

  4. 所以,我想建议一个解决方案来阻止所有这些问题 - class Image作为temp中原始数据的包装/访问者:

    #include <cstddef>
    #include <cstdint>
    
    struct RGB {
      uint8_t red, green, blue;
    
      RGB() { } // leaving contents uninitialized
      RGB(uint8_t red, uint8_t green, uint8_t blue):
        red(red), green(green), blue(blue)
      { }
    };
    
    class Image {
      private:
        const uint8_t *_pData;
      public:
        class Row {
          private:
            const uint8_t *_pData;
          public:
            Row(const uint8_t *pData): _pData(pData) { }
    
            RGB operator[](size_t i) const
            {
              const uint8_t *pixel = _pData + 3 * i;
              return RGB(pixel[0], pixel[1], pixel[2]);
            }
        };
    
        Image(const uint8_t *pData): _pData(pData) { }
    
        size_t height() const { return _pData[0]; }
        size_t width() const { return _pData[1]; }
    
        RGB get(size_t i, size_t j) const
        {
          const uint8_t *pixel = _pData + 2 + (i * _pData[1] + j) * 3;
          return RGB(pixel[0], pixel[1], pixel[2]);
        }
    
        Row operator[](size_t i) const
        {
          return Row(_pData + 2 + i * _pData[1] * 3);
        }
    };
    

    可以使用Image::get()以及更直观的Image::operator[]()来访问RGB-tripel。

    示例代码:

    #include <iomanip>
    #include <iostream>
    
    int main()
    {
      // data array representing image data - this would really be a bin fle
      //                    header         r,    g,    b        r,    g,    b      r,    g,    b      footer
      uint8_t temp[22] = { 0x02, 0x03,    0x01, 0x02, 0x03,   0x04, 0x05, 0x06,   0x07, 0xef, 0x05,
                                          0x0a, 0x01, 0x02,   0x0d, 0xfe, 0x00,   0x10, 0xff, 0xff,   0xef, 0xef };
      // access via
      Image img(temp);
      std::cout << std::hex << std::setfill('0');
      // via Image::get()
      std::cout << "access with img.get(i, j):\n";
      for (size_t i = 0, n = img.height(); i < n; ++i) {
        for (size_t j = 0, m = img.width(); j < m; ++j) {
          RGB rgb = img.get(i, j);
          std::cout << "  "
            << std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
            << std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
            << std::setw(2) << (unsigned)rgb.blue << std::setw(0);
        }
        std::cout << '\n';
      }
      // via Image::operator[]
      std::cout << "access with img[i][j]:\n";
      for (size_t i = 0, n = img.height(); i < n; ++i) {
        for (size_t j = 0, m = img.width(); j < m; ++j) {
          RGB rgb = img[i][j];
          std::cout << "  "
            << std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
            << std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
            << std::setw(2) << (unsigned)rgb.blue << std::setw(0);
        }
        std::cout << '\n';
      }
      return 0;
    }
    

    输出:

    access with img.get(i, j):
      01 02 03  04 05 06  07 ef 05
      0a 01 02  0d fe 00  10 ff ff
    access with img[i][j]:
      01 02 03  04 05 06  07 ef 05
      0a 01 02  0d fe 00  10 ff ff
    

    Live Demo on coliru

相关问题