2015-01-31 2 views
1

Я пытаюсь сделать простой конвертер изображений (формат ppm к пользовательскому), и у меня возникла проблема с методом ifstream.read. Несмотря на это:ifstream.read только читает половину файла

int rows,cols, maxV; 
    char header [100], *ptr; 


    std::ifstream im; 
    //open image in binary format 
    im.open(name.c_str(), std::ios::in | std::ios::binary); 

    if (!im) 
    { 
     std::cout << "Can't read image!" << std::endl; 
     exit(1); 
    } 

    //read the header of the image 
    im.getline(header, 3,'\n'); 
    //test if header is P6 
    if ((header[0] != 80) || (header[1] != 54)) 
    { 
     std::cout << "Image" << name << "is not .ppm format" << std::endl; 
    } 

    //get next line for height and width 
    im.getline(header,100,'\n'); 
    //dont read the comments 
    while (header[0] == '#') 
     im.getline(header,100,'\n'); 

    //number of columns, rows 
    cols = strtol(header, &ptr, 0); 
    rows = strtol(header, &ptr, 0); 
    maxV = strtol(header, &ptr, 0); 

    const int rows1=rows; 
    const int cols1=cols; 


    Component * tbuffer; 
    const_cast<Component*> (tbuffer); 
    tbuffer = new Component[rows1*cols1 * 3]; 

    im.read((char *)tbuffer, cols*rows * 3); 
    std::cout << tbuffer[3000000] << std::endl; 
    im.close(); 

Он читает только 2.700.007 элементы выхода из 4.320.000 образа я пытаюсь читать. поэтому tbuffer [3.000.000] будет «cout» NULL. Я что-то пропустил?

Изменить: О компоненте:

typedef unsigned char Component; 

EDIT2: Изображение 1200 * 1200 (смещ_по_столбцы * строка). 2.700.007 - последний индекс tbuffer со значением в нем. остальная часть tbuffer остается пустой

+2

Добро пожаловать в Переполнение стека. Возможно, вам захочется вырезать пух (приветствия) и сделать его [MCVE] (https://stackoverflow.com/help/mcve), поэтому нам не нужно так много догадываться, что остальное в вашем коде. Если вы взяли [тур] (http://stackoverflow.com/tour), возможно, вы уже знаете, что пытаетесь это сделать. Мы можем догадаться, что ошибаемся, и поэтому не находим фатальной ошибки! – Deduplicator

+1

Что такое 'Компонент'? – Axalo

+0

Извините, я забыл про Компонент. Отредактировано –

ответ

0

PPM format, который вы читаете, не гарантирует, что магическое число P6 будет завершено новой строкой, или что за остальной частью заголовка следует новая строка, ни то, что lentgh, heigth и maxV находятся на одной линии.

Но главная проблема, что у вас есть

cols = strtol(header, &ptr, 0); // you start at the begin of the header 
rows = strtol(header, &ptr, 0); // you start again at the begin of the header 
maxV = strtol(header, &ptr, 0); // and another time !! 

Так что ваши строки и MAXV не могли быть значения в файле. Следует --regardless другие изменения above-- упоминалось скорее использовать:

cols = strtol(header, &ptr, 0); // you start at the begin of the header 
rows = strtol(ptr, &ptr, 0); // continue after the first number 
maxV = strtol(ptr, &ptr, 0); // ... 

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

Я предлагаю вам следующую функцию полезности, чтобы пропустить пробелы и комментарии в соответствии с форматом PPM:

ifstream& skipwcmt(ifstream& im) { 
    char c; 
    do { 
     while ((c = im.get()) != EOF && isspace(c)) ; 
     if (isdigit(c)) 
      im.unget(); 
     else if (c == '#') 
      while ((c = im.get()) != EOF && c != '\n' && c != '\r'); 
    } while (isspace(im.peek())); 
    return im; 
} 

Вы можете использовать эту функцию для чтения заголовка, как здесь:

// ... 
// check magic number 
im.read(header, 2); 
if ((header[0] != 'P') || (header[1] != '6')) 
{ 
    std::cout << "Image" << name << "is not .ppm format" << std::endl; 
    exit(1); 
} 
skipwcmt(im) >> cols; 
skipwcmt(im) >> rows; 
skipwcmt(im) >> maxV; 
if (!isspace(im.get())) { // folowed by exactly one whitespace ! 
    std::cout << "Image" << name << "has a corrupted header" << std::endl; 
    exit(1); 
} 

// display the header to check the data 
cout << "cols=" << cols << ", rows=" << rows << ", maxcol=" << maxV << endl; 

Примечание: Я не знаю, будут ли файлы, которые вы должны прочитать, иметь maxV < = 255. Теоретически вы можете иметь значения до 65535, и в этом случае вам нужно будет прочитать 2 байта для цветного cmponent вместо одного.

+0

У меня было это так, и gcount в конце дал мне хороший 0. Я предполагаю, что это было вызвано всем вышеперечисленным. Спасибо, попробуй как можно скорее! –

+0

Спасибо, это помогло! –

+0

@ Françoisl'Olonnais: Вы можете принять и откликнуться на ответ. Ни один из них не является обязательным, но если ответ решает вашу проблему, обычно имеет смысл также продвигать его. –

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