2016-03-23 17 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; 
} 

Bu kodu farklı ppm görüntüleri üzerinde çalıştırdığımda, aslında rgb değerlerini doğru şekilde ayıklamakta, ancak sorun bunun tamamen yapılmamasıdır. Temel 800 x 800 görüntü 640000 piksele sahip ve bu kod yaklaşık 40800'ü okuyor ve artık yokmuş gibi bitiyor.ppm p6 görüntünün tamamlanması için okuma sorunları. C++

Bunun ppm formatının kendisinin yanlış anlaşılmasından kaynaklandığını düşünüyorum. Yazı tipi, genişlik ve boyut ve sihirli sayıya sahip olan başlık biçiminin ötesinde, yalnızca bir satır daha ve daha fazla '\ n' karakterin olmadığını düşündüm. Bu nedenle matris, bitişik bir karakter dizisi olarak okunabilir.

Peki bu program neden böyle garip bir yerde duruyor?

cevap

0

C++ ile iyi değilim ama burada neyin yanlış olduğunu açıklamaya çalışacağım.

Dosya türü p6 ise, daha sonra görüntü verileri bayt formatında saklanır, her renk bileşeni için bir bayt (r, g, b). Kodunuzdaki yorumdan her zaman p6 beklediğiniz gibi görünüyor. Bu, matrisin üstlendiğiniz gibi sürekli bir veri bloğu olarak ilerleyeceği anlamına gelir. Diğer seçenekler, renk bileşenlerini ASCII biçiminde saklayan p3'dur (örnek 0 0 0).

Sorun şu ki, p6 dosya türünde veri bloğu ikilidir ve siz onu bir dize olarak ele alıyorsunuz. Bu, r, G, B bir piksel göz önünde = (65, 13, 10) gibi bir ikili olarak kodlanmış olması:

0x41, 0xD, 0xA 

getline ASCII karakter A değerlendirir, ancak sonra okuma durur ilk baytı okuyacak 0xD0xA, getline için bir sınırlayıcı olan yeni satır karakteri (Windows'ta) olan \r\n olduğundan.

yerine:

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; 

NOT: matris bloğundan önce hat renk bileşeni için maksimum değeri içeren, PPM bu belirtiyor

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

ben böyle bir şey yapsın 255'ten büyük olabilir, bu nedenle char dizisi yeterince iyi olmayacak ve short dizisine en az (2 bayt) ihtiyaç duyacağınız için dikkatli olmanız gerekir (2 bayt)

Faydalı linkler:

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

sayesinde şimdi bunun farkında. – DoingItForTheCorgi

+0

Dizideki yazdırma elemanları boş alanlar mı veriyor? printf ("% d% c% c% c \ n", i/3, kırmızı, yeşil, mavi); çalışmıyor. ve hiçbiri cout << "" kırmızı << "" << yeşil << "" << mavi; – DoingItForTheCorgi

+0

@DoingItForTheCorgi, "cout << static_cast (pixelData [i]) ile çalış" –