[英]Reading binary PBM file ending with distorted image
我正在嘗試實現一個 C++ 代碼來讀取二進制 PBM 文件。 現在,在成功讀取文件的 header(幻數、寬度和高度)后,我得到了這段代碼來讀取文件的每個字符,並從該字符中提取各個位:
std::vector<pixel> v;
char c;
while(input_file.get(c)) {
for(int i=0; i<8; i++) {
pixel p;
p.r = p.g = p.b = (c & (1 << i)) != 0;
v.push_back(p);
}
}
之后,我將這個向量的數據傳輸到一個矩陣:
int h = stoi(height), w = stoi(width);
int counter = 0;
for(int i=0; i<h; i++) {
std::vector<pixel> row;
for(int j=0; j<w; j++) row.push_back(v[counter++]);
image.push_back(row);
}
有了這個,當我嘗試在屏幕上可視化圖像時,我得到了一個扭曲的圖像,其中一些像素似乎與它原來的 position 錯位了。我得到了以下生成 ascii 圖像的程序,該圖像顯示了讀取二進制文件后得到的內容文件:
struct Pixel {
int r, g, b;
};
typedef struct Pixel pixel;
int main(int argc, char *argv[])
{
if(argc < 3) return 1;
std::string input = argv[1];
std::string output = argv[2];
std::ifstream input_file(input);
std::ofstream output_file(output);
std::vector<std::vector<pixel>> image;
std::vector<pixel> v;
std::string line_one, line_two, line_pixels;
char magicNumber;
std::string width, height;
while(getline(input_file, line_one)) {
if(line_one.size() > 0 && line_one.at(0) != '#') {
magicNumber = line_one.at(1);
break;
}
}
while(getline(input_file, line_two)) {
if(line_two.size() > 0 && line_two.at(0) != '#') {
std::stringstream ss(line_two);
getline(ss, width, ' ');
getline(ss, height, ' ');
break;
}
}
std::cout << magicNumber << std::endl;
std::cout << width << " " << height << std::endl;
if(magicNumber == '4') {
std::vector<pixel> v;
char c;
while(input_file.get(c)) {
for(int i=0; i<8; i++) {
pixel p;
p.r = p.g = p.b = (c & (1 << i)) != 0;
v.push_back(p);
}
}
int h = stoi(height), w = stoi(width);
int counter = 0;
for(int i=0; i<h; i++) {
std::vector<pixel> row;
for(int j=0; j<w; j++) row.push_back(v[counter++]);
image.push_back(row);
}
}
output_file << "P1" << std::endl << width << " " << height << std::endl;
for(int i=0; i<stoi(height); i++) {
for(int j=0; j<stoi(width); j++) {
output_file << image[i][j].r << " ";
}
output_file << std::endl;
}
return 0;
}
我在測試中嘗試讀取的圖像是這個。 誰能告訴我這里出了什么問題? 讀取文件后如何獲得相同的圖像?
我能夠加載圖像:
據我所知,主要問題是您的代碼從最低有效位向上讀取每個字節,但像素是從最高有效位向下存儲的(這確實很奇怪)。
例如,您可以將(c & (1 << i)) != 0
更改為(c & (1 << (i ^ 7))) != 0
讀取不是 8 倍寬的行末尾的額外填充位本身不應該是一個問題,但是當您將像素“去線性化”到 2D 網格中時,您必須注意您的矢量包含填充位: w
不是行的寬度,它是圖像“有用部分”的寬度。
具體來說,有這段代碼就可以了:
for(int i=0; i<8; i++) {
pixel p;
p.r = p.g = p.b = (c & (1 << (i ^ 7))) != 0;
v.push_back(p);
}
但是你應該小心使用寬度四舍五入到 8 的倍數:
for(int i=0; i<h; i++) {
std::vector<pixel> row;
for(int j=0; j < ((w + 7) & -8); j++) row.push_back(v[counter++]);
image.push_back(row);
}
((w + 7) & -8)
將w
向上舍入為 8 的倍數,還有其他方法可以做到這一點。 輸出結果的循環應該使用w
,而不是四舍五入的w
。
是否簽名的字符應該沒有任何區別, c
可能是負數,但您實際閱讀的位不會受到影響。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.