如何确保DirectDraw曲面具有正确的文件格式?

时间:2018-08-22 20:18:47

标签: c# .net binaryfiles dds-format

我需要简单检查dds文件是否为有效格式。我只需要对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格式是否有效)以及如何使用可以以一种简单的方式实现代码以检查dds格式。任何帮助将不胜感激。

编辑: 因此,感谢@NaCl,我已经回答了问题的第一部分。现在,我知道dds文件中需要哪些部分,但不知道如何在dds文件中找到它。我已经用十六进制编辑器打开了许多dds文件,但是我不是很擅长逆向工程,因此我无法理解需要检查的字节位于何处,这将使我不知道如何实现代码。可以在指定位置搜索字节(由于找到了有关该文件的更多文档,因此可以使用png文件进行搜索),因为我不知道要定位到什么位置。

如果有人可以指出正确的方向或以其他方式帮助我,我将非常感激。谢谢。

1 个答案:

答案 0 :(得分:3)

具有头文件的第一件事是检查其幻数(如果文档中有任何数字),对于DDS file,幻数为0x44445220等于“纯文本”中的"DDS "

之后,只需处理规格即可。一切(魔术数字除外)均以小尾数格式存储,因此在处理字节时要小心,根据Microsoft的说法,DDS标头的definition为(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)

以上代码已在此存储库https://github.com/toji/webgl-texture-utils/tree/master/sample/img上的.dds个文件中进行了测试,两个文件的标头完全相同:

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的值检查整个内容。

希望这会有所帮助:)