2016-03-23 8 views
2
int main(){ 
    std::fstream myfile; // file object is created 
    myfile.open ("green.ppm"); 
    std::string line; 

    unsigned red,green,blue; //to output values on 0 -255 scale. 
    int width, height = 0; 
    if (myfile.is_open()) 
    { 
     std::getline (myfile,line);  //type of file, skip, it will always be for this code p6 
     std::getline (myfile,line);  // width and height of the image 
     std::stringstream lineStream(line); //extract the width and height; 
     lineStream >> width; 
     lineStream >> height; 
     // std::cout<< width << " " << height <<" \n"; 
     getline (myfile,line);    //skip magic number 
     getline (myfile,line);    // reach the matrix of numbers 
      for (int i = 0; i<(width*height*3) ; i= i+3){ 
     char num = line[i]; uint8_t number = num; red = number; 
      num = line[i+1]; number = num; green = number; 
      num = line[i+2]; number = num; blue = number; 
     std::cout<<"pixel " << i/3 << " is " << red << " " << green << " " << blue << std::endl; 
     } 


//char to uint_8t to unsigned is a basic an inefficient way I found that takes the pixel rgb values in my ppm file and allows me to interpret them from a range of 0-255 

     } 

    // cout<<counter<<endl; 
    myfile.close(); 
    return 0; 
} 

Wenn ich diesen Code über verschiedene ppm-Bilder ausführen extrahiert es tatsächlich die RGB-Werte korrekt aber das Problem ist, dass es nicht vollständig tut. ein grundlegendes 800 x 800 Bild hat 640000 Pixel und dieser Code liest ungefähr 40800 und endet dann, als ob es dort nicht mehr gäbe.Probleme beim Lesen von ppm p6-Bild bis zum Abschluss. C++

Ich denke, das ergibt sich aus einem Missverständnis der ppm-Format selbst. Ich dachte, dass über das Header-Format hinaus, das die Datei mit dem Typ, der Breite und der Größe und der magischen Zahl ist, nur eine weitere Zeile und keine '\ n' Zeichen mehr vorhanden waren. Daher könnte die Matrix als ein zusammenhängendes Array von Zeichen gelesen werden.

Warum stoppt dieses Programm an solch einem seltsamen Ort?

Antwort

0

Ich bin nicht gut mit C++, aber ich werde versuchen zu erklären, was hier falsch ist.

Wenn der Dateityp p6 ist, dann werden die Bilddaten im Byte-Format gespeichert, ein Byte pro Farbkomponente (r, g, b). Aus dem Kommentar in Ihrem Code scheint es, dass Sie immer p6 erwarten. Dies bedeutet, dass die Matrix als ein zusammenhängender Block von Daten gespeichert wird, wie Sie annehmen. Andere Option ist p3, die Farbkomponenten im ASCII-Format speichert (Beispiel 0 0 0).

Das Problem ist, dass in p6 Typ Datei der Datenblock binär ist und Sie behandeln es als Zeichenfolge. Betrachten Sie diese, ein Pixel mit r, g, b = (65, 13, 10) würde in binär wie folgt codiert werden:

0x41, 0xD, 0xA 

getline ersten Byte gelesen wird, die A zu ASCII-Zeichen auswertet, sondern stoppen nach dem Lesen es, weil 0xD0xA\r\n ist, ein Newline-Zeichen (unter Windows), das ein Trennzeichen für getline ist.

Statt:

getline (myfile,line);    // reach the matrix of numbers 

würde ich so etwas tun:

int bufsz = 3*width*height; 
char* pixelData = new char[bufsz]; 
myfile.read(pixelData,bufsz); 

for (int i = 0; i < bufsz; i+=3) { 
    unsigned char red = pixelData[i]; 
    unsigned char green = pixelData[i+1]; 
    unsigned char blue = pixelData[i+2]; 
    // use unsigned char to express range [0,255], 
    // this may make compiler to issue warnings 
    // but it should be safe to do a cast 
} 

// don't forget to release pixelData when done with it, 
// maybe use smart pointers 
delete[] pixelData; 

HINWEIS: Die Zeile vor dem Matrixblock für eine Farbkomponente max-Wert enthält, der PPM heißt es, dass diese kann größer als 255 sein, so dass Sie in diesen Fällen vorsichtig sein müssen, da das char Array nicht gut genug ist und Sie short Array mindestens (2 Bytes)

benötigen

Hilfreiche Links:

  1. Netpbm format
  2. basic_istream::read
+0

Dank ich merke es jetzt. – DoingItForTheCorgi

+0

Wie kommt es, dass das Drucken von Elementen im Array leere Bereiche ergibt? printf ("% d% c% c% c \ n", i/3, rot, grün, blau); funktioniert nicht. und keiner ist cout << "" rot << "" << grün << "" << blau; – DoingItForTheCorgi

+0

@DoingItForTheCorgi versuchen mit 'cout << static_cast (pixelData [i])' –