2016-10-30 10 views
0

PPM 이미지 (P3)를 읽으려는 코드를 얻으 려하고 제대로 작동하지 않습니다. 아이디어는 3 개의 부호없는 문자를 가져 와서 RGB에 저장하는 것입니다. 그러나 현재로서는 첫 번째 특성을 취하고 나머지는 무시하는 결과를 낳습니다. 186 0 255 | |ifstream :: read는 reinterpret_cast를 사용하여 서명되지 않은 char을 읽지 않습니다.

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; 
} 

주는 표준 : : cout을 나의 시나리오에서 출력하도록되어 있지만, 대신에 내가 얻을 | | 1 8 6.


편집 : ++ 메모장에서 열 때 파일 (original.ppm이)이 (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 
... 

결과는 같아야합니다 유념하라 . 픽셀 [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 |을 출력합니다." 내가 입력 한 내용이 텍스트 형식이라는 것을 추론합니다. 즉, 구성 요소는 2 진수 바이트로 인코딩되지 않지만 10 진수로 표시된 해당 바이트의 텍스트 표현으로 인코딩됩니다. 그럼에도 불구하고 당신은'ifs.read (..., 3)'와 그 다음 3 개의 assgn에서 3 바이트로 읽으려고합니다. –

답변

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; 

당신은 바이너리 모드로 파일을 열 필요가 있습니다. 그러나 나는 그것이 필요하다고 생각하지 않는다. 당신이 문자열로 정확히 2 바이트를 읽으려면

당신의 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

문자열의 크기를 조정하면 문자열의 문자 수만 조정되므로 위의 작업을 수행하면 st [0] = 1 및 st [1] = 8로 읽습니다. 이는 작동하지 않습니다. –