Я понимаю, что нет никакой причины для реализации функции, которая читает значения пикселей изображения pgm на c ++, но я должен сделать это для своего назначения.
По причине точности, после того, как я прочитал значения пикселей, я сравнил их со значениями пикселей, считанными в matlab с помощью imread (файл), однако некоторые значения совпадают, а некоторые отключены, и я не уверен, почему.
Ниже приведена функция для c ++, изображение в двоичном формате:
int Read_File_PGM(string filename){
int row = 0, col = 0, numrows = 0, numcols = 0, bits;
string filename;
ifstream infile(filename.c_str(), ios::binary);
stringstream ss;
string inputLine = "";
// First line : version
getline(infile,inputLine);
if(inputLine.compare("P5") != 0) cerr << "Version error" << endl;
//else cout << "Version : " << inputLine << endl;
// Second line : width and height
ss << infile.rdbuf();
ss >> numrows >> numcols;
int max_bits;
ss >> max_bits;
unsigned char pixel;
unsigned int pixel_value[numrows][numcols];
//double sum = 0;
// Following lines : datafor(row = 0; row < numrows; ++row){
for (col = 0; col < numcols; ++col){
infile.read(pixel, 1);
ss >> pixel;
pixel_value[row][col] = (int)pixel;
}
}
infile.close();}
return 0;
}
Как написано, ваш код не компилируется. После добавления некоторых заголовков и т. Д. Я все же натолкнулся на пару ошибок.
Первое — вы повторно объявляете «имя файла» — это параметр функции, но у вас есть строка
string filename;
Сразу после int row = 0 …etc
Во-вторых, мой компилятор (правильно) не любит вашу строку
infile.read(pixel, 1);
Сообщение об ошибке (это даже не предупреждение — это ошибка)
readPgm.cpp:34: error: invalid conversion from ‘unsigned char’ to ‘char*’
readPgm.cpp:34: error: initializing argument 1 of
‘std::basic_istream<_CharT, _Traits>&
std::basic_istream<_CharT,_Traits>::read(_CharT*, std::streamsize)
[with _CharT = char, _Traits = std::char_traits<char>]’
Но на самом деле — я не думаю, что вам нужна эта строка вообще — потому что следующая строка
ss >> pixel;
и так как вы уже связали ss
с файловым буфером, когда вы сделали
ss << infile.rdbuf();
Я думаю, что вы можете просто прочитать пиксели сейчас.
Однако обратите внимание, что ваш код неявно предполагает, что максимальное значение < 255 (один байт на пиксель). Стандарт определяет, что вы должны искать двойные байты, если число> 255. Вы можете рассмотреть возможность обработки этого случая отдельно.
Тем не менее — для крошечного тестового файла, который я сделал, следующий модифицированный код хорошо справился с чтением. Посмотрите, работает ли это лучше для вас?
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int Read_File_PGM(string filename)
{
int row = 0, col = 0, numrows = 0, numcols = 0, bits;
stringstream ss;
ifstream infile(filename.c_str(), ios::binary);
string inputLine = "";
// First line : version
getline(infile,inputLine);
if(inputLine.compare("P5") != 0) cerr << "Version error" << endl;
cout << "Version : " << inputLine << endl;
// Second line : width and height
ss << infile.rdbuf();
ss >> numrows >> numcols;
int max_bits;
ss >> max_bits;
char pixel;
unsigned int pixel_value[numrows][numcols];
cout << "rows: " << numrows << "; cols: " << numcols << endl;
cout << "max size: " << max_bits << endl;
// Following lines : data
for (row = 0; row < numrows; ++row){
for (col = 0; col < numcols; ++col){
ss >> pixel;
pixel_value[row][col]= pixel;
cout << (int)pixel << ";";
}
cout << endl;
}
infile.close();
}
int main(void) {
Read_File_PGM("testfile.pgm");
return 0;
}
Для тестового файла я создал следующее. Обратите внимание, что значение ASCII 1
является 49
, так далее.
P5
5 5 255
12345
23456
34567
45678
56789
Вывод вышеуказанной программы:
Version : P5
rows: 5; cols: 5
max size: 255
49;50;51;52;53;
50;51;52;53;54;
51;52;53;54;55;
52;53;54;55;56;
53;54;55;56;57;
Заключительная мысль: вы также должны помнить, что в C последний индекс является «быстрым», а в Matlab — первым. В зависимости от того, как вы сравниваете вещи, которые могут иметь значение.
Других решений пока нет …