我正在尝试使用libpng来读取png 一个Qt资源。问题:班级正在阅读 不应该具有Qt的依赖性。
在第一步中,阅读http://www.piko3d.net/tutorials/libpng-tutorial-loading-png-files-from-streams/#CustomRead我已经成功编写了一个函数
read_png(istream& in)
我也成功传递了一个普通的ifstream
ifstream in("abs_path_to_png/icon.png");
到 read_png(..)并让它成功读取png。但是如何获得 a(最好是平台独立的)来自Qt资源吗?性能 这不是什么大问题,所以我最初想出了
bool Io_Qt::get_istringstream_from_QFile(QFile& qfile, istringstream& iss)
{
// [.. Some checking for existence and the file being open ..]
QString qs(qfile.readAll());
iss.str(qs.toStdString());
// I also tried: QByteArray arr(qfile.readAll()); iss.str(arr.data());
return qfile.isOpen();
}
// Someplace else iss and qfile are created like this:
istringstream iss(std::stringstream::in | std::stringstream::binary);
QFile qfile(":/res/icon.png");
qfile.open(QIODevice::ReadOnly);
这实际上产生了一个乍看之下看起来很好的问题
cout << "'" << iss.str().c_str() << "'" << endl;
我得到了
'�PNG
'
但似乎有一些空白问题。对于
ifstream in("abs_path_to_png/icon.png");
char c;
cout << "'";
for (int j=0;j<8;j++)
{
in >> c;
cout << c;
}
cout << "'" << endl;
产量
'�PNG'
虽然后者工作,但前一种变体最终导致libpng检查函数 png_sig_cmp(..)拒绝我的png无效。我的第一反应是&#34;二进制&#34;。但是:
你看到我错过了吗?
答案 0 :(得分:1)
您正在处理这些流,就像它们是带有词法提取运算符的文本数据一样。查看ios::binary
以及使用二进制流时适用的read
和write
方法。
我会在你的案件中彻底放弃operator<<
和operator>>
,而赞成read
和write
。使用ostream::write
写入从QIODevice::readAll()
返回的字节数组数据,将其内容传输到临时字符串流,例如,在测试中使用ostream::read
来验证其内容。
确保正确传输的一个好的测试用例是编写一个测试来从QFile读取内容,使用ostream::write
将其传输到二进制输出文件流(ofstream
),然后尝试在图像软件中加载它以查看它是否正常。然后使用字符串流交换文件流,并在工作时将其传递给libpng
。
答案 1 :(得分:0)
正如艾克所说,似乎确实存在差异 以文本为中心的运营商'&gt;&gt;','&lt;&lt;'和'.str(..)'相反的东西 以二进制为中心的命令,如'.read'和'.write'。再加上它 关于正确初始化流。当我终于得到这个程序 做我想要的福音是这样的:
首先,我在QFile旁边使用了一个普通的字符串流:
// Explicitly setting flags should at least contain ::in and ::out
// stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary)
// However, the default constructor is perfectly fine.
stringstream ss;
QFile qfile(":/res/icon.png");
qfile.open(QIODevice::ReadOnly);
我传给了我的函数,现在看起来像这样:
bool Io_Qt::get_stringstream_from_QFile(QFile& qfile, stringstream& ss)
{
// [.. some sanity checks..]
QDataStream in(&qfile);
uint len = qfile.size();
char* c = (char*)malloc(len*sizeof(char));
in.readRawData(c,len);
ss.write(c,len);
free (c);
return true;
}
此流已填充,并且大小合适。特别是从 无论如何,.write(..)都会写入所需的字符数 数据中有多少个零。我最大的问题是 我不愿意在AND中使用std :: stringstream :: std :: stringstream :: out同时激活因为 组合对我来说似乎有些古怪。但两者都需要。 但是,我发现我可能会跳过std :: stringstream :: binary。 但是因为它似乎没有任何伤害我喜欢 保持好运。尽管如此,请随意评论这种迷信! : - )
答案 2 :(得分:0)
更干净,更少C-ish,更多Qt / C ++ -ish版本可以是:
QFile file(filePath);
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
std::istringstream iss(data.toStdString());
现在使用iss
,在我的情况下这是用于libTIFF:
TIFF* tif = TIFFStreamOpen("MemTIFF", &iss);
// ...
此外,对于PNG,您现在可以关注already posted article,因为std::istringstream
的类型为std::istream
。
注意,此解决方案涉及将文件数据完全加载到内存中。