【问题标题】:Open a pgm image 16 bpp [closed]打开 pgm 图像 16 bpp [关闭]
【发布时间】:2017-06-28 15:38:45
【问题描述】:

我需要将每像素 16 位的 pgm 图像转换为每像素 8 位的 pgm 图像,但我无法读取 16 bpp 的 pgm 图像,我不明白我做错了什么。这里是代码:

#include "pgm.h"

#include <iterator>
#include <algorithm>
#include <fstream>
#include <sstream>

using namespace std;

bool convert16to8bit(const std::string& inFilename, mat<uint8_t>& img, const std::string& outFilename){
    mat<uint16_t> imgTemp;

    ifstream is(inFilename, ios::binary);
    if (!is)
        return false;

    string magic;
    is >> magic;
    if (magic != "P2" && magic != "P5")
        return false;

    size_t rows, cols, nlevels;
    is >> cols >> rows >> nlevels;

    if (nlevels < 255)
        return false;

    is.get();

    img = mat<uint8_t>(rows, cols);
    if (nlevels == 255){
        if (magic == "P5"){
            is.unsetf(ios::skipws);
            img.data_.assign(istream_iterator<uint8_t>(is), istream_iterator<uint8_t>());
        }else
            img.data_.assign(istream_iterator<int>(is), istream_iterator<int>());
    }
    else{
        imgTemp = mat<uint16_t>(rows, cols);
        if (magic == "P5"){
            is.unsetf(ios::skipws);
            imgTemp.data_.assign(istream_iterator<uint16_t>(is), istream_iterator<uint16_t>());
        }
        else
            imgTemp.data_.assign(istream_iterator<int>(is), istream_iterator<int>());

        for (size_t r = 0; r < rows; r++)
            for (size_t c = 0; c < cols; c++)
                img(r, c) = imgTemp(r, c);
    }

    stringstream ss; 
    ss << outFilename << ".pgm";
    ofstream os(ss.str(), ios::binary);
    if (!os)
        return false;
    os << magic <<"\n" << cols << " " << rows << "\n255\n";
    if (magic == "P2") 
        copy(begin(img), end(img), ostream_iterator<int>(os, " ")); 
    else 
        copy(begin(img), end(img), ostream_iterator<uint8_t>(os));

    return true;
}


//mat.h

#if !defined MAT_H 
#define MAT_H

#include <vector>

template <typename T> 
struct mat {
    size_t rows_, cols_; 
    std::vector<T> data_;

    mat(size_t rows = 0, size_t cols = 0) : rows_(rows), cols_(cols), data_(rows*cols) {}

    const size_t rows() const { return rows_; } 
    const size_t cols() const { return cols_; }

    const T& operator()(size_t r, size_t c) const { return data_[r*cols_ + c]; } 
    T& operator()(size_t r, size_t c) { return data_[r*cols_ + c]; }

    auto begin() -> decltype(data_.begin()) { return data_.begin(); } 
    auto end() -> decltype(data_.end()) { return data_.end(); } 
    auto begin() const -> decltype(data_.begin()) { return data_.begin(); } 
    auto end() const -> decltype(data_.end()) { return data_.end(); }
};
#endif // MAT_H

此代码在尝试使用 pgm 16bpp 但使用 pgm 8bpp 执行指令 img(r, c) = imgTemp (r, c)(错误:向量下标超出范围)时会产生错误,我可以打开它没有问题并将其重新创建为没有错误的原始文件。我认为问题出在 istream_iterator 因为 istream_iterator 有效(使用 pgm 8bit)。有什么解决办法吗?

感谢您的帮助

【问题讨论】:

  • 究竟有什么解决方案? “我在阅读 pgm 图像时遇到问题”不是问题陈述。您能否更准确地说明什么不起作用?
  • 我无法读取和记忆 16 位大小的 imgTemp.data_ 像素
  • 你有例外吗?编译器错误?具有您不期望的值的变量?这是可以帮助我们帮助您的信息。您能否收集它们并编辑您的问题以包含它们?
  • 尝试执行指令时产生错误 img(r, c) = imgTemp (r, c) (error: vector subscript out of range)
  • 为什么要重新发明轮子?尝试使用 OpenCV。 imread 函数将读取 PGM,我相信您可以指定位深度。否则试试 freeimage。

标签: c++ pgm


【解决方案1】:

我找到了解决问题的方法。如果它对某人有用,这是正确的代码:

#include "pgm.h"

#include <iterator>
#include <algorithm>
#include <fstream>
#include <sstream>

using namespace std;

bool convert16to8bit(const std::string& inFilename, mat<uint8_t>& img, const std::string& outFilename){
    mat<uint16_t> imgTemp;

    ifstream is(inFilename, ios::binary);
    if (!is)
        return false;

    string magic;
    is >> magic;
    if (magic != "P2" && magic != "P5")
        return false;

    size_t rows, cols, nlevels;
    is >> cols >> rows >> nlevels;

    if (nlevels < 255)
        return false;

    is.get();

    img = mat<uint8_t>(rows, cols);
    if (nlevels == 255){
        if (magic == "P5"){
            is.unsetf(ios::skipws);
            img.data_.assign(istream_iterator<uint8_t>(is), istream_iterator<uint8_t>());
        }else
            img.data_.assign(istream_iterator<int>(is), istream_iterator<int>());
    }
    else{
        imgTemp = mat<uint16_t>(rows, cols);
        if (magic == "P5"){

            //here is the line changed
            is.read(reinterpret_cast<char *>(&imgTemp.data_[0]), imgTemp.rows()*imgTemp.cols() * 2);          
        }
        else
            imgTemp.data_.assign(istream_iterator<int>(is), istream_iterator<int>());

        for (size_t r = 0; r < rows; r++)
            for (size_t c = 0; c < cols; c++)
                img(r, c) = imgTemp(r, c);
    }

    stringstream ss; 
    ss << outFilename << ".pgm";
    ofstream os(ss.str(), ios::binary);
    if (!os)
        return false;
    os << magic <<"\n" << cols << " " << rows << "\n255\n";
    if (magic == "P2") 
        copy(begin(img), end(img), ostream_iterator<int>(os, " ")); 
    else 
        copy(begin(img), end(img), ostream_iterator<uint8_t>(os));

    return true;
}

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2021-07-11
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    相关资源
    最近更新 更多