Beispiel #1
0
 /// <summary>
 /// Loads a DDS texture from an input stream.
 /// </summary>
 public static Texture2DInfo LoadDDSTexture(Stream inputStream, bool flipVertically = false)
 {
     using (var r = new BinaryFileReader(inputStream))
     {
         // Check the magic string.
         var magicString = r.ReadBytes(4);
         if (!"DDS ".EqualsASCIIBytes(magicString))
         {
             throw new FileFormatException($"Invalid DDS file magic string: \"{Encoding.ASCII.GetString(magicString)}\".");
         }
         // Deserialize the DDS file header.
         var header = new DDSHeader();
         header.Read(r);
         if ("DX10".EqualsASCIIBytes(header.ddspf.dwFourCC))
         {
             var header2 = new DDSHeader_DXT10();
             header2.Read(r);
         }
         // Figure out the texture format and load the texture data.
         ExtractDDSTextureFormatAndData(header, r, out var hasMipmaps, out var ddsMipmapLevelCount, out var textureFormat, out var bytesPerPixel, out var textureData);
         // Post-process the texture to generate missing mipmaps and possibly flip it vertically.
         PostProcessDDSTexture((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel, hasMipmaps, (int)ddsMipmapLevelCount, textureData, flipVertically);
         return(new Texture2DInfo((int)header.dwWidth, (int)header.dwHeight, textureFormat, hasMipmaps, textureData));
     }
 }
Beispiel #2
0
        /// <summary>
        /// Extracts a DDS file's texture format and pixel data.
        /// </summary>
        static void ExtractDDSTextureFormatAndData(DDSHeader header, GenericReader r, out bool hasMipmaps, out uint DDSMipmapLevelCount, out TextureFormat textureFormat, out int bytesPerPixel, out byte[] textureData)
        {
            hasMipmaps = Utils.ContainsBitFlags((int)header.dwCaps, (int)DDSCaps.Mipmap);
            // Non-mipmapped textures still have one mipmap level: the texture itself.
            DDSMipmapLevelCount = hasMipmaps ? header.dwMipMapCount : 1;
            // If the DDS file contains uncompressed data.
            if (Utils.ContainsBitFlags((int)header.ddspf.dwFlags, (int)DDSPixelFormats.RGB))
            {
                // some permutation of RGB
                if (!Utils.ContainsBitFlags((int)header.ddspf.dwFlags, (int)DDSPixelFormats.AlphaPixels))
                {
                    throw new NotImplementedException("Unsupported DDS file pixel format.");
                }
                // some permutation of RGBA
                else
                {
                    // There should be 32 bits per pixel.
                    if (header.ddspf.dwRGBBitCount != 32)
                    {
                        throw new FileFormatException("Invalid DDS file pixel format.");
                    }
                    // BGRA32
                    if (header.ddspf.dwBBitMask == 0x000000FF && header.ddspf.dwGBitMask == 0x0000FF00 && header.ddspf.dwRBitMask == 0x00FF0000 && header.ddspf.dwABitMask == 0xFF000000)
                    {
                        textureFormat = TextureFormat.BGRA32;
                        bytesPerPixel = 4;
                    }
                    // ARGB32
                    else if (header.ddspf.dwABitMask == 0x000000FF && header.ddspf.dwRBitMask == 0x0000FF00 && header.ddspf.dwGBitMask == 0x00FF0000 && header.ddspf.dwBBitMask == 0xFF000000)
                    {
                        textureFormat = TextureFormat.ARGB32;
                        bytesPerPixel = 4;
                    }
                    else
                    {
                        throw new NotImplementedException("Unsupported DDS file pixel format.");
                    }

                    if (!hasMipmaps)
                    {
                        textureData = new byte[header.dwPitchOrLinearSize * header.dwHeight];
                    }
                    // Create a data buffer to hold all mipmap levels down to 1x1.
                    else
                    {
                        textureData = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel)];
                    }
                    r.ReadRestOfBytes(textureData, 0);
                }
            }
            else if ("DXT1".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT1ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else if ("DXT3".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT3ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else if ("DXT5".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT5ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else
            {
                throw new NotImplementedException("Unsupported DDS file pixel format.");
            }
        }