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

Когда я запускаю этот код по разным изображениям ppm, он действительно извлекает значения rgb правильно, но проблема в том, что он не делает это целиком. базовое изображение 800 x 800 имеет 640000 пикселей, и этот код читает около 40800, а затем заканчивается так, как будто его больше нет.Проблемы с чтением ppm p6 до завершения. C++

Я думаю, что это связано с непониманием формата ppm. Я думал, что за пределами формата заголовка, который является файлом с типом, шириной и размером, и магическим номером, была только одна строка и не более символов «\ n». Поэтому матрицу можно было бы читать как непрерывный массив символов.

Так почему же эта программа останавливается в таком нечетном месте?

ответ

0

Я плохо разбираюсь в C++, но я попытаюсь объяснить, что здесь не так.

Если тип файла p6, тогда данные изображения сохраняются в байтовом формате, по одному байту на компонент цвета (r, g, b). Из комментария в вашем коде кажется, что вы всегда ожидаете p6. Это означает, что матрица будет храниться как один непрерывный блок данных, как вы предполагаете. Другая опция - p3, которая хранит цветовые компоненты в формате ASCII (пример 0 0 0).

Проблема заключается в том, что в файле типа p6 блок данных является двоичным, и вы рассматриваете его как строку. Рассмотрю это, пиксель с R, G, B = (65, 13, 10) будет закодирован в двоичной системе следующим образом:

0x41, 0xD, 0xA 

getline будет читать первые байты, которое приводится к ASCII символу A, но остановит чтение после того, как потому что 0xD0xA - это \r\n, символ новой строки (в Windows), который является разделителем для getline.

Вместо:

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

Я хотел бы сделать что-то вроде:

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; 

ПРИМЕЧАНИЕ: Предпоследняя строка матрицы блока содержит максимальное значение для компонента цвета, РРМ утверждает, что это может быть больше 255, поэтому вам нужно быть осторожным в этих случаях, так как массив char не будет достаточно хорошим, и вам понадобится массив short не менее (2 байта)

Полезные ссылки:

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

Спасибо Я понимаю, что это сейчас. – DoingItForTheCorgi

+0

Как печатаются элементы массива в пустых пространствах? printf ("% d% c% c% c \ n", i/3, красный, зеленый, синий); не работает. и ни один cout << "" красный << "" << зеленый << "" << синий; – DoingItForTheCorgi

+0

@DoingItForTheCorgi попробовать с 'cout << static_cast (pixelData [i])' –

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