С++ преобразование двоичного (P5) изображения в ascii (P2) изображение (.pgm)

Я пишу простую программу для преобразования двоичного кода в градациях серого (P5) в ascii в градациях серого (P2), но у меня возникают проблемы с чтением двоичного кода и преобразованием его в int.

#include <iostream>
#include <fstream>
#include <sstream>
using namespace::std;

int usage(char* arg) {
// exit program
    cout << arg << ": Error" << endl;
    return -1;
}

int main(int argc, char* argv[]) {
    int rows, cols, size, greylevels;
    string filetype;

    // open stream in binary mode
    ifstream istr(argv[1], ios::in | ios::binary);
    if(istr.fail()) return usage(argv[1]);

    // parse header
    istr >> filetype >> rows >> cols >> greylevels;
    size = rows * cols;

    // check data
    cout << "filetype: " << filetype << endl;
    cout << "rows: " << rows << endl;
    cout << "cols: " << cols << endl;
    cout << "greylevels: " << greylevels << endl;
    cout << "size: " << size << endl;

    // parse data values
    int* data = new int[size];
    int fail_tracker = 0; // find which pixel failing on
    for(int* ptr = data; ptr < data+size; ptr++) {
        char t_ch;
        // read in binary char
        istr.read(&t_ch, sizeof(char));
        // convert to integer
        int t_data = static_cast<int>(t_ch);
        // check if legal pixel
        if(t_data < 0 || t_data > greylevels) { 
            cout << "Failed on pixel: " << fail_tracker << endl;
            cout << "Pixel value: " << t_data << endl;
            return usage(argv[1]);
        }
        // if passes add value to data array
        *ptr = t_data;
        fail_tracker++;
    }
    // close the stream
    istr.close();

    // write a new P2 binary ascii image
    ofstream ostr("greyscale_ascii_version.pgm");
    // write header
    ostr << "P2 " << rows << cols << greylevels << endl;
    // write data
    int line_ctr = 0;
    for(int* ptr = data; ptr < data+size; ptr++) {
        // print pixel value
        ostr << *ptr << " ";
        // endl every ~20 pixels for some readability
        if(++line_ctr % 20 == 0) ostr << endl;
    }
    ostr.close();

    // clean up
    delete [] data;
    return 0;
}

пример изображения — взято из старого сообщения. Удален комментарий в файле изображения, так как теперь меня не беспокоит эта функция.

При компиляции с помощью g++ я получаю вывод:

$> ./a.out a.pgm
filetype: P5
rows: 1024
cols: 768
greylevels: 255
size: 786432
Failed on pixel: 1
Pixel value: -110
a.pgm: Error

Изображение представляет собой небольшую утку, и значение пикселя не может быть -110 ... где я ошибаюсь? Спасибо.


person tubby    schedule 26.10.2012    source источник


Ответы (3)


уровни серого: 255

-110 - это 146 как беззнаковый символ. Похоже, вы находитесь на платформе, где char является подписанным типом, попробуйте использовать неподписанный char.

person stonemetal    schedule 26.10.2012
comment
изменен istr.read(&t_ch, sizeof(char)); в беззнаковый символ t_ch = istr.get(); и оставил все то же самое, и это работало отлично. Благодарю. - person tubby; 27.10.2012

Если у вас не может быть отрицательных значений, используйте unsigned int * вместо int* для указателей пикселей. Таким образом, у вас не будут значения, считанные как значения со знаком

person user18428    schedule 26.10.2012
comment
как бы вы сделали это для двойного? в основной программе, которую я пишу, я читаю значения в класс, где мне нужно найти стандартное отклонение, среднее значение и т. Д. для расчетов. Я попытался изменить t_data и тип приведения на unsigned int, и программа не удалась на пикселе 1: Значение пикселя: 4294967186 - person tubby; 27.10.2012

Вам нужна коррекция в выводе:

ostr << "P2\n" << rows << " "<< cols << " "<<  greylevels << endl;
person andre    schedule 09.07.2015