2016-10-30 4 views
0

Я пытаюсь получить мой код для чтения изображения PPM (P3), и он не работает должным образом. Идея состоит в том, чтобы получить 3 символа без знака и сохранить их в RGB. Но на данный момент это приводит только к тому, чтобы взять первого персонажа и игнорировать остальных.ifstream :: read not reading unsigned char, даже с reinterpret_cast

Image Image::readImg(std::string const &filename) { 
    std::ifstream ifs; 
    ifs.open(filename.c_str(), std::ios::binary); 
    Image _in; 
    try { 
     if (ifs.fail()) { 
      throw("Can't open input file"); 
     } 
     std::string header; 
     int w, h, max; 
     ifs >> header; 
     if (strcmp(header.c_str(), "P3") != 0) throw("Can't read input file"); 
     ifs >> w >> h >> max; 
     _in.init(w, h); 
     ifs.ignore(256, '\n'); 
     unsigned char pix[3]; 
     for (int i = 0; i < h; ++i){ 
      for (int j = 0; j < w; ++j){ 
       ifs.read(reinterpret_cast<char *>(pix), 3); 
       _in.pixels[i][j].R = pix[0]; 
       _in.pixels[i][j].G = pix[1]; 
       _in.pixels[i][j].B = pix[2]; 
      } 
     } 
     std::cout << "|" << _in.pixels[0][0].R << " " << _in.pixels[0][0].G << " " << _in.pixels[0][0].B << "|"; 
     ifs.close(); 
    } 
    catch (const char *err) { 
     fprintf(stderr, "%s\n", err); 
     ifs.close(); 
    } 
    return _in; 
} 

Обратите внимание на станд :: соиЬ предполагается выход в моем сценарии | 186 0 255 |, но вместо этого я получаю | 1 8 6 |.


EDIT: Файл (original.ppm), при открытии в Notepad ++, выглядит следующим образом (UNIX/UTF-8):

P3 
1024 768 
255 
186 0 255 186 0 255 186 0 255 186 0 255 186 0 255 186 0 255 186 1 255 
186 1 254 186 1 254 185 2 254 185 2 254 185 1 254 185 2 253 185 3 253 
185 2 252 185 3 252 185 3 252 185 3 252 185 3 251 184 4 251 184 4 251 
184 4 251 184 4 251 184 5 250 184 5 250 183 5 250 183 6 249 183 6 249 
183 6 249 183 6 248 183 7 249 183 7 249 183 7 248 183 7 247 183 8 247 
182 7 247 182 8 246 183 9 247 183 9 246 183 9 246 182 9 246 181 9 246 
182 9 246 181 10 245 182 10 245 181 10 244 181 10 245 181 11 244 181 11 244 
... 

Результат должен быть: _in. пиксели [0] [0] .R = 186 _in.pixels [0] [0] .G = 0 _in.pixels [0] [0] .B = 255 и продолжать сбор RGB всех пикселей в файле.

+0

'operator >>' предназначен для чтения текста с разделителями пробелов. Если за «P3» следует пробел, в файле это не сработает. –

+0

Это не проблема, но не используйте исключения для потока управления. Вам не нужно закрывать файл; деструктор сделает это. Поэтому, когда вы обнаруживаете ошибку, распечатайте сообщение и верните его. –

+0

«Обратите внимание, что std :: cout должен выводиться в моем сценарии | 186 0 255 |, но вместо этого я получаю | 1 8 6 |.» Из которого я выводил ваш ввод, форматируется текст - это означает, что компоненты не закодированы как двоичные байты, а как текстовое представление этих байтов, написанных в десятичной форме. И все же вы пытаетесь прочитать их как 3 байта в вашем 'ifs.read (..., 3)' и следующем 3 assgns. –

ответ

0

[Обновлено] Это должно работать:

int pix[3]; // not an unsigned char 
... 
ifs >> pix[0] >> pix[1] >> pix[2]; 

вместо:

ifs.read(reinterpret_cast<char *>(pix), 3); 

Как вы относитесь к ширине и высоте?

ifs >> w >> h >> max; 
+0

По-прежнему та же проблема. Он определяет, что 1 8 и 6 - все отдельные символы, когда они должны быть одним сплоченным символом без знака. –

+0

Ваши '_in.pixels [i] [j] .R' также являются символами? Если это так, используйте значения temp int/uint для чтения. Я обновил ответ с ним. –

+0

Выход только что стал скремблированным беспорядком символов. –

0

Использование >> операций в потоках пропускает пробелы по умолчанию.

Если вы хотите сохранить все символы, то сделать (прежде чем читать из него):

ifs >> std::noskipws; 

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

, если вы хотите прочитать ровно два байта в строке, которую вы можете использовать это вместо GetLine:

std::string st; 
st.resize(2); 
ifs.read(&st[0], st.size()); 
+0

Сделал первый бит, это не проблема, учитывая, как файл выложен (см. Новое редактирование в OP). Уже в двоичном режиме. и std :: string st (2); не компилируется должным образом. –

+0

использовать вместо std :: string st {}; st.resize (2); – dmg

+0

String resize, по внешнему виду только изменяет размер # символов в строке, поэтому, выполняя вышеуказанное, он будет читать st [0] = 1 и st [1] = 8. Это не сработает. –

Смежные вопросы