首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在Linux上读取DDS图像标头

无法在Linux上读取DDS图像标头
EN

Stack Overflow用户
提问于 2013-05-20 15:59:23
回答 3查看 2K关注 0票数 1

我使用DDS实用程序加载Nvidia nv_dds图像文件,以便在OpenGL程序中使用。它可以在Windows上工作,但在Linux (Ubuntu12.10)上失败。我原以为是nv_dds的问题,但后来发现在Linux上fread()读取带有错误偏移量的头字节(GCC 4.7)。

这是读取DDS文件标记,然后读取DDS标头的块:

代码语言:javascript
复制
// 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():

代码语言:javascript
复制
// 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.The的imageHeight属性中,其余的属性仍然是垃圾。

当我在Windows机器上测试它时,所有这些都不会发生。有没有可能fread()在带有MSVC编译器的Linux和Windows上的工作方式不同?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-21 16:22:08

我解决了这个问题,因为没有提出有用的输入,所以我将自己回答这个问题。

我发现了这个post,我开始怀疑不同compilers.Then之间数据类型大小的差异。之后,我发现DDS header的大小(用GCC编译)是248,这是正常大小的两倍。(微软规范说它必须是124字节).nv_dds dds header使用unsigned long作为其成员:

代码语言:javascript
复制
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编译器将无符号的长整型视为4字节,而在Linux8 bytes.From上的GCC则是报头的两倍大小。我将其全部更改为unsigned int (也在DDS_PIXELFORMAT标头中):

代码语言:javascript
复制
 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一起工作。

票数 2
EN

Stack Overflow用户

发布于 2013-06-20 01:49:27

对于GCC来说,32位编译时是4字节,64位编译时是8字节。可以使用选项-m32或-m64显式目标32位或64位。

票数 2
EN

Stack Overflow用户

发布于 2013-08-21 08:37:25

对于ABI相关的任务,你应该总是使用在stdint.h中定义的类型名中描述其大小的类型,比如int32_t/uint64_t,这样可以在不同的平台上编译时省去很多问题。(除了大/小端问题)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16645040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档