簡體   English   中英

讀取以失真圖像結尾的二進制 PBM 文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM