Не могу прочитать заголовок образа DDS в Linux

я использую Nvidia nv_dds утилита для загрузки файлов изображений DDS для использования в программе OpenGL. Он работает в Windows, но не работает в Linux (Ubuntu 12.10). Сначала я подумал о проблеме с nv_dds, но потом обнаружил, что fread () читает байты заголовков с неправильным смещением в Linux (GCC 4.7)

Это блок, который читает маркер файла 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 )

Затем я получаю значение ширины изображения в свойстве imageHeight объекта DDS_HEADER. Остальные свойства все еще являются ненужными.

Всего этого не происходит, когда я тестирую его на компьютере с Windows.
Возможно ли, что fread () работает в Linux GCC иначе, чем в Windows с компилятором MSVC?

1

Решение

С GCC long составляет 4 байта при компиляции для 32 бит и 8 байтов для 64 бит. Использование может использовать опцию -m32 или -m64 для явного назначения 32 или 64 бит.

2

Другие решения

Я решил это, и поскольку никакой полезной информации не было предложено, я сам отвечу на этот вопрос.

Я начал подозревать различия в размерах типов данных между разными компиляторами. Затем я нашел это сообщение. После этого я обнаружил, что размер заголовка DDS (компилируется с GCC) составляет 248, что в два раза больше, чем должно быть (спецификации MS говорят, что оно должно быть точно 124 байта). Заголовок 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 байта, в то время как GCC в Linux 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 не является кросс-платформенным (или / и кросс-компиляционным чтением), и этот хак должен быть сделан, чтобы заставить его работать с GCC в Linux.

1

Для задач, связанных с ABI, вы всегда должны использовать типы, размер которых описан в имени типа, которое определено в stdint.h, например, int32_t / uint64_t, это может спасти много проблем во время компиляции на разных платформах (кроме большой / маленькой последовательности) )

0
По вопросам рекламы [email protected]