1

Nvidia nv_ddsユーティリティを使用して、OpenGL プログラムで使用する DDS イメージ ファイルをロードします。Windowsでは機能しますが、Linux(Ubuntu 12.10)では失敗します。最初はnv_ddsの問題を考えていましたが、Linux(GCC 4.7)でfread()がヘッダーバイトを間違ったオフセットで読み取ることがわかりました

これは、DDS ファイル マーカーを読み取り、次に DDS ヘッダーを読み取るブロックです。

// open file
FILE *fp = fopen(filename.c_str(),"rb");
if (fp == NULL) {
    return false;
}
// read in file marker, make sure its a DDS file

char filecode[4];
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
    fclose(fp);
    return false;
}

// read in DDS header
DDS_HEADER ddsh;
fread(&ddsh, 1,sizeof(DDS_HEADER)  , fp);

DDS_HEADER インスタンスの内容に目を通すと、いくつかの実際の値が間違ったプロパティに割り当てられており、残りはがらくたであることがわかります。

次に、「DDS」マーカーをコメントアウトすると、 fread() を確認します。

// open file
FILE *fp = fopen(filename.c_str(), "rb");
if (fp == NULL) {
    return false;
}
// read in file marker, make sure its a DDS file
/* comment out for test
char filecode[4];
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
    fclose(fp);
    return false;
}
*/
// read in DDS header
DDS_HEADER ddsh;   
fread(&ddsh, sizeof( DDS_HEADER ),1 , fp);//sizeof( DDS_HEADER )

次に、DDS_HEADER の imageHeight プロパティに画像の幅の値を取得します。残りのプロパティはまだジャンクです。

Windowsマシンでテストすると、これはすべて起こりません。Linux GCC と MSVC コンパイラを使用する Windows では、fread() の動作が異なる可能性はありますか?

4

3 に答える 3

2

GCC では、long は 32 ビット用にコンパイルされた場合は 4 バイト、64 ビット用にコンパイルされた場合は 8 バイトです。オプション -m32 または -m64 を使用して、32 ビットまたは 64 ビットを明示的にターゲットにすることができます。

于 2013-06-19T17:49:26.960 に答える
2

私はこれを解決しましたが、有用な入力が提案されなかったため、この質問に自分で答えます。

異なるコンパイラ間のデータ型サイズの違いについて疑い始めました。その後、この投稿を見つけました。その後、DDS ヘッダー (GCC でコンパイル) のサイズが 248 であることを発見しました。これは、本来あるべきサイズの 2 倍です (MS 仕様では、正確に 124 バイトでなければならないと言われています)。nv_dds dds ヘッダーは、メンバーに unsigned long を使用します。

typedef struct 
 {
    unsigned long dwSize;
    unsigned long dwFlags;
    unsigned long dwHeight;
    unsigned long dwWidth;
    unsigned long dwPitchOrLinearSize;
    unsigned long dwDepth;
    unsigned long dwMipMapCount;
    unsigned long dwReserved1[11];
    DDS_PIXELFORMAT ddspf;
    unsigned long dwCaps1;
    unsigned long dwCaps2;
    unsigned long dwReserved2[3];

  }DDS_HEADER;

そのため、MSVC コンパイラは unsigned long を 4 バイトとして扱い、Linux の GCC は 8 バイトとして扱うようです。ここから、ヘッダーの倍のサイズになります。すべて unsigned int に変更しました (DDS_PIXELFORMAT ヘッダーでも):

 typedef struct 
 {
    unsigned int dwSize;
    unsigned int dwFlags;
    unsigned int dwHeight;
    unsigned int dwWidth;
    unsigned int dwPitchOrLinearSize;
    unsigned int dwDepth;
    unsigned int dwMipMapCount;
    unsigned int dwReserved1[11];
    DDS_PIXELFORMAT ddspf;
    unsigned int dwCaps1;
    unsigned int dwCaps2;
    unsigned int dwReserved2[3];


 }DDS_HEADER;

そして今、それはすべて機能します!したがって、いくつかの場所で言われていることに反して、NVidia nv_dds はクロスプラットフォーム (またはクロスコンパイル読み取り) ではなく、Linux 上の GCC で動作させるにはこのハックを行う必要があります。

于 2013-05-21T08:22:08.197 に答える