2

Qt リソースから png を読み取るために libpng を使用しようとしています。問題点: 読み取りを行うクラスには、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 を正常に読み取らせます。しかし、Qt リソースから (できればプラットフォームに依存しない) istream を取得するにはどうすればよいでしょうか? パフォーマンスは大きな問題ではないので、最初に思いついた

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);

実際、これは、一見すると良さそうに見える iss を生成します。

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 を無効として拒否します。私の最初の反射は「バイナリ」についてです。でも:

  1. istringstream iss(std::stringstream::in | std::stringstream::binary); 正しいと感じます。
  2. QIODevice::ReadOnly にはバイナリ パートナーがないようです。

私が見逃したものが見えますか?

4

3 に答える 3

0

アイクが言うように、実際には、「.read」のようなバイナリ中心のコマンドとは対照的に、テキスト中心の演算子「>>」、「<<」、および「.str(..)」のようなものの違いについてのようです。そして書く'。さらに、ストリームを正しく初期化することも重要です。私が最終的に私が望んでいたことを行うプログラムを手に入れたとき、福音は次のようになりました:

最初に、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(..) は、データ内のゼロの数に関係なく、必要な数の文字を書き込むためです。私の最大の問題は、 std::stringstream::in と std::stringstream::out の両方を同時にアクティブにするのが嫌だったことです。それでも両方必要です。ただし、std::stringstream::binary をスキップする可能性があることがわかりました。でも害はないようなので、幸運のために取っておきたいと思います。ただし、この迷信についてはお気軽にコメントしてください。:-)

于 2015-05-06T18:47:54.613 に答える