Я понимаю, что нет причин для реализации функции, которая считывает значения пикселей изображения 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 : data
for(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. Вы можете рассмотреть вопрос о том, что этот случай отдельно.
Тем не менее - для небольшого тестового файла, который я сделал, следующий модифицированный код выполнил работу по чтению OK. Посмотрите, работает ли это лучше для вас?
#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 - первым. В зависимости от того, как вы сравниваете вещи, которые могут иметь значение.