Как читать двоичные данные из файла после успешного чтения заголовка ascii в файле

Я пытаюсь прочитать формат изображения Netpbm, следуя описанной здесь спецификации . Типы ascii для формата (которые имеют P1, P2 и P3 в качестве магического числа) я могу читать без проблем. Но у меня проблемы с чтением двоичных данных в этих файлах (с P4, P5 и P6 в качестве магического числа) - заголовок файла (который является ascii) я могу прочитать без проблем.

В ссылке указано, что:

В двоичных форматах PBM использует 1 бит на пиксель, PGM использует 8 или 16 бит на пиксель, а PPM использует 24 бита на пиксель: 8 для красного, 8 для зеленого, 8 для синего. Некоторые устройства для чтения и записи могут поддерживать 48 бит на пиксель (по 16 для R,G,B), но это все еще редкость.

при этом я пытаюсь использовать этот ответ для чтения данных по крупицам и получаю этот код :

      if(*this->magicNumber == "P4") {
  this->pixels = new Matrix<int>(this->width, this->height);

  vector<int> p;
  while(getline(file, line_pixels)) {
    if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
      string byte;
      stringstream ss(line_pixels);
      while(getline(ss, byte)) {
        unsigned char c = (unsigned char)byte.at(0);
        for(int x=0; x != 8; x++) p.push_back( (c & (1 << x)) != 0 );
      }
    }
  }

  int count = 0;
  for(int i=0; i<height; i++) {
    for(int j=0; j<width; j++) {
      this->pixels->set(i, j, p[count++]);
    }
  }
}

но когда я пытаюсь прочитать изображение с именем sample_640×426.pbm по этой ссылке , я должен получить такой результат:

но вместо этого я получаю этот результат:

Для двоичного формата для изображений PGM и PPM, когда я пытаюсь открыть изображение, я получаю ошибку ошибки сегментации при попытке увеличить countв какой-то момент выполнения цикла. Я думаю, как-то размер vector<int> pзаканчивается больше, чем ожидаемый продукт width x height.

код формата PGM:

      if(*this->magicNumber == "P5") {
  this->pixels = new Matrix<int>(this->width, this->height);

  vector<int> p;
  while(getline(file, line_pixels)) {
    if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
      string number;
      stringstream ss(line_pixels);
      while(getline(ss, number)) {
        unsigned char data = (unsigned char)number.at(0);
        p.push_back((int)data);
      }
    }
  }

  int count = 0;
  for(int i=0; i<height; i++) {
    for(int j=0; j<width; j++) {
      this->pixels->set(i, j, p[count++]);
    }
  }
}

код для формата PPM:

      if(*this->magicNumber == "P6") {
  this->pixels = new Matrix<struct Pixel>(this->width, this->height);

  vector<int> p;
  while(getline(file, line_pixels)) {
    if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
      string byte;
      stringstream ss(line_pixels);
      while(getline(ss, byte)) {
        unsigned char data = (unsigned char)byte.at(0);
        p.push_back((int)data);
      }
    }
  }

  int count = 0;
  for(int i=0; i<height; i++) {
    for(int j=0; j<width; j++) {
      struct Pixel pixel;
      pixel.r = p[count++];
      pixel.g = p[count++];
      pixel.b = p[count++];
      this->pixels->set(i, j, pixel);
    }
  }
}

Кто-нибудь может подсказать, что я здесь делаю неправильно?

1 ответ

      while(getline(file, line_pixels)) {

читает из входного потока до тех пор, пока не будет прочитан символ новой строки.

Файл есть файл. Он содержит байты. Считаете ли вы, что файл содержит текст или двоичный файл, это чисто вопрос интерпретации.

Текстовые строки заканчиваются символом новой строки. Вот что делает: он читает байты из файла, пока не прочитает символ новой строки. Все, что прочитано, попадает в параметр.

Это было бы очень запутанно, если бы вы хотели прочитать некоторые двоичные данные, например изображение. Байт, содержащий то же значение, что и символ новой строки, может естественным образом встречаться в двоичном файле, таком как файл изображения, представляя соответствующие значения пикселей. С использованием чтение нетекстовых данных всегда заканчивается слезами.

Это имело бы смысл только в одной ситуации: если вы заранее знаете, что двоичные данные, которые вы намереваетесь здесь прочитать, заканчиваются байтом, который просто является символом новой строки, и этот символ новой строки больше нигде не появляется.

Но, конечно, в файле изображения у вас нет таких гарантий вообще.

При чтении данных изображения обычно ожидается, что вы прочитаете определенное количество байтов из файла.

Здесь вы заранее знаете размер вашего изображения и его формат. Исходя из этого, вы можете с помощью простой математической формулы рассчитать, сколько байтов вы ожидаете прочитать.

И это то, чтометод делает: считывает определенное количество байтов из файла. Эта ссылка содержит дополнительную информацию.

Вам необходимо заменить весь показанный код, который неправильно использует с тем, который использует .

Другие вопросы по тегам