Как я могу убедиться, что поверхность DirectDraw имеет правильный формат файла?
Мне нужно сделать простую проверку, если файл ддс имеет правильный формат. Мне просто нужно сделать общую проверку файла dds, поэтому мне не нужно проверять, является ли это dxt1, dxt5, dx10 и т. Д. Например, если у меня есть изображение png и я переименую расширения в.dds в формате dds будет, конечно, неправильно, и тогда мне нужно будет сказать пользователю, что он пытается использовать файл dds с неверным форматом. Однако, если у меня есть dds, который действительно имеет правильный формат файла, мне не нужно будет проводить дальнейшее расследование, так как мне все равно, какой это тип файла dds (на данный момент). Так что мне нужно только прочитать части файла dds, которые останутся неизменными во всех файлах dds. Я думаю, что мог бы каким-то образом прочитать заголовок dds и магическое число. Я должен сделать ту же проверку для файла PNG, и там я читаю заголовок PNG, как это:
var png = new byte[] { 0x89, 0x50, 0x4e, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }
using (FileStream fs = new FileStream(fileToCheck, FileMode.Open, FileAccess.Read))
{
if (fs.Length > buffer.Length)
{
fs.Read(buffer, 0, buffer.Length);
fs.Position = (int)fs.Length - endBuffer.Length;
fs.Read(bufferEnd, 0, endBuffer.Length);
}
fs.Close();
}
for (int i = 0; i < png.Length; i++)
{
if (buffer[i] != png[i])
return false;
}
return true;
И я искал, есть ли похожий способ проверить формат файла dds. Я новичок в этом, и проблема, с которой я сталкиваюсь, состоит в том, чтобы узнать, какие байты в файле dds всегда будут одинаковыми для всех файлов dds (чтобы я мог проверить эти байты, чтобы убедиться, что формат dds действителен) и как я может реализовать код простым способом, чтобы проверить формат ддс. Любая помощь будет оценена.
Редактировать: Так что благодаря @NaCl я получил ответ на первую часть вопроса. Теперь я знаю, какие части в файле dds требуются, но я не знаю, как найти его в файле dds. Я открыл много файлов dds с помощью шестнадцатеричного редактора, но я не очень хорош в обратном инжиниринге, поэтому я не могу понять, где находятся байты, которые мне нужно проверить, что, кроме того, заставит меня не знать, как я могу реализовать код искать байты в указанных позициях (что я могу сделать с файлом png, так как я нашел гораздо больше документов об этом файле), так как я не знаю, в какую позицию идти.
Если кто-то может указать мне правильное направление или помочь мне каким-либо другим способом, я был бы очень признателен. Благодарю.
1 ответ
Первое, что нужно сделать с файлом, имеющим заголовок, - это проверить его магические числа (если они есть в документации), в случае файла DDS, магическое число 0x44445220
который равен "DDS "
в "обычном тексте".
После этого просто разберитесь со спецификациями. Все (кроме магического числа) хранится в формате с прямым порядком байтов, поэтому будьте осторожны при работе с байтами, согласно Microsoft, определение заголовка DDS - (C++):
typedef struct {
DWORD dwSize; /* Always equal to 124 */
DWORD dwFlags;
DWORD dwHeight;
DWORD dwWidth;
DWORD dwPitchOrLinearSize;
DWORD dwDepth;
DWORD dwMipMapCount;
DWORD dwReserved1[11];
DDS_PIXELFORMAT ddspf;
DWORD dwCaps;
DWORD dwCaps2;
DWORD dwCaps3;
DWORD dwCaps4;
DWORD dwReserved2;
} DDS_HEADER;
Исходя из этого, я просто пришел со следующим кодом для любого "общего" файла DDS:
public static bool IsValidDDS(string path)
{
if (path == null)
throw new ArgumentNullException(nameof(path));
if (!File.Exists(path)) // Check for existence.
return false;
uint magicNumber = 0; byte[] headerLength = new byte[sizeof(byte)];
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] magic = new byte[sizeof(uint)];
// I'm still pretty used to C and fread, so here you go :^)
if (fs.Read(magic, 0, sizeof(uint)) != sizeof(uint))
return false; // Not even a valid file.
if (fs.Read(headerLength, 0, sizeof(byte)) != sizeof(byte))
return false; // Not enough bytes, even if the first 4 bytes were checked.
// Convert to a big endian integer.
magicNumber = (uint)((magic[0] << 24) | (magic[1] << 16) | (magic[2] << 8) | magic[3]);
}
return (headerLength[0] == 0x7C) && (magicNumber == 0x44445320);
}
Приведенный выше код просто проверяет первые 5 байтов входного файла (передается в качестве аргумента path
), они всегда такие же, как я видел, и должны быть равны:
0x44 0x44 0x53 0x20 0x7C 0x00 0x00 0x00 (8 bytes)
Код выше был протестирован с .dds
файлы в этом хранилище: https://github.com/toji/webgl-texture-utils/tree/master/sample/img, и оба файла имеют одинаковый заголовок:
iamnacl:~/workspace $ cd dds-test/
iamnacl:~/workspace/dds-test $ dotnet run ../test-dxt1.dds
The file is a valid DDS file? True
iamnacl:~/workspace/dds-test $ dotnet run ../test-dxt5.dds
The file is a valid DDS file? True
iamnacl:~/workspace/dds-test $
Вы можете оптимизировать код выше, чтобы выполнить один вызов fs.Read
с размером ulong
и проверьте все это по этому значению: 0x444453207C000000
,
Надеюсь это поможет:)