Данные изображения C ++ RGB, наложенные на двумерный массив (вектор векторов) - PullRequest
0 голосов
/ 24 мая 2018

Учитывая данные изображения, как я могу наложить значения RGB на вектор векторов.Из кода ниже;У меня есть массив типа uint8_t, представляющий изображение, затем я переинтерпретирую 3 байта в структуру RGB и помещаю их в 2D-массив в цикле for.

Это работает (ниже снимок экрана), но чувствует, что 'неуклюжий », есть ли другой способ достичь того же?(возможно, с помощью итератора для вектора векторов, 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 голосов
/ 24 мая 2018
  1. ИМХО, vector<vector< >> подходит, если строки могут иметь различную длину, но на самом деле это больше не называется матрицей.(Необработанные данные образца OP формируют матрицу, сохраняемую построчно.)

  2. Почему необходимо скопировать массив temp в vector<>?Это дублирует данные.Если срок службы может быть предоставлен, temp может быть доступен напрямую.(В противном случае его можно скопировать в vector<uint8_t>.)

  3. AFAIK, упаковка компонентов в struct RGB не предоставляется.Следовательно, reinterpret_cast<RGB*>() не самый чистый способ доступа к байтам.

Итак, я хотел бы предложить решение, которое предотвращает все эти проблемы - 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);
    }
};

Доступ к RGB-tripel может быть выполнен с помощью Image::get(), а также с более интуитивным Image::operator[]().

Пример кода:

#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

Живая демонстрация на coliru

...