Использование std :: vector для сохранения карты пикселей BMP - PullRequest
1 голос
/ 30 апреля 2019

Я использую std :: vector для сохранения пиксельной карты изображения BMP:

struct BGR {
  BYTE &operator[](const BMPCOLORS &color)
  {
    switch (color) {
      case BLUE: return b;
      case GREEN: return g;
      case RED: return r;
    }
    throw ERROR_OUT_OF_BOUNDS;
  }

  DWORD operator()() //return rgb
  {
    return static_cast <DWORD> ((r << 16) | (g << 8) | b);
  }

  BGR()
  : b(0), g(0), r(0)
  {}

  BGR(const BYTE *BGR) : b(BGR[0]), g(BGR[1]), r(BGR[2]) {}
  BGR(BYTE blue, BYTE green, BYTE red) : b(blue), g(green), r(red) {}
  BYTE b, g, r;
};

А функция чтения карты пикселей выглядит следующим образом:

int BMPimage::ReadImagePixels(void)
{
  if (!my_image_->working_file.is_open())
    return BMP_ERR_READING_FILE;

  DWORD height = my_image_->height;
  DWORD width = my_image_->width;

  BYTE pad_offset = static_cast <BYTE> (( ((width * 3 + 3) & static_cast <unsigned int> (~3)) - (width * 3) ) * sizeof(BYTE));
  BGR temp;

  my_image_->working_file.seekg(my_image_->file_header->bfOffBits);

  for (unsigned int row = 0; row < width; row++)
  {
    for (unsigned int col = 0; col < height; col++)
    {
        my_image_->working_file.read(reinterpret_cast <char*> (&temp), sizeof(BGR));
        pixels.push_back(temp);
    }
    my_image_->working_file.seekg(pad_offset, std::ios::cur);
  }

  return BMP_OK;
}

Там my_image_->height и my_image_->width принимают значения из BITMAPINFOHEADER, поэтому оно должно быть правильным (я проверил функции чтения заголовков BMP, и это правильно).

Но в некоторых случаях с правильными типами изображений (24-битный формат и версия Microsoft V3, нет сжатия), я получаю ошибки вне диапазона :

terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 262144) >= this->size() (which is 262144)

Пример функции там я получаю:

int ImgEdit::make_black_and_white()
{
    int width = static_cast<int> (bmpImg->get_width());
    int height = static_cast<int> (bmpImg->get_height());
    int avg;

    for (int row = 0; row < width; row++)
    {
        for (int col = 0; col < height; col++)
        {
            avg = (bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).r +
            bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).g +
            bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).b) / 3;
            bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).r = static_cast<unsigned char>(avg);
            bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).g = static_cast<unsigned char>(avg);
            bmpImg->pixels.at(static_cast<unsigned long> ( (row * width) + col)).b = static_cast<unsigned char>(avg);
        }
    }

    return 0;
}

Если я пытаюсь использовать try-catch, это исключение, я получаю черно-белое результирующее изображение с цветной линией на левой стороне. Поэтому я не понимаю, почему это произошло и как исправить эту ошибку с помощью вектора.

P.S. Я работаю в системе Linux, поэтому я определил:

typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;

1 Ответ

0 голосов
/ 30 апреля 2019
terminate called after throwing an instance of 'std::out_of_range'  what():  
vector::_M_range_check: __n (which is 262144) >= this->size() (which is 262144)

Это происходит потому, что std::vector проверяет, находятся ли ваши индексы в допустимом диапазоне.

Кажется, ваша конкретная проблема связана с тем, что вы включили width и height вКод цикла.

...