public void Read(UnityBinaryReader r) { var size = r.ReadLEUInt32(); if (size != 124) { throw new FileFormatException($"Invalid DDS file header size: {size}."); } dwFlags = (DDSFlags)r.ReadLEUInt32(); if (!Utils.ContainsBitFlags((int)dwFlags, (int)DDSFlags.Height, (int)DDSFlags.Width)) { throw new FileFormatException($"Invalid DDS file flags: {dwFlags}."); } dwHeight = r.ReadLEUInt32(); dwWidth = r.ReadLEUInt32(); dwPitchOrLinearSize = r.ReadLEUInt32(); dwDepth = r.ReadLEUInt32(); dwMipMapCount = r.ReadLEUInt32(); dwReserved1 = new uint[11]; for (var i = 0; i < 11; i++) { dwReserved1[i] = r.ReadLEUInt32(); } ddspf = new DDSPixelFormat(r); dwCaps = (DDSCaps)r.ReadLEUInt32(); if (!Utils.ContainsBitFlags((int)dwCaps, (int)DDSCaps.Texture)) { throw new FileFormatException($"Invalid DDS file caps: {dwCaps}."); } dwCaps2 = (DDSCaps2)r.ReadLEUInt32(); dwCaps3 = r.ReadLEUInt32(); dwCaps4 = r.ReadLEUInt32(); dwReserved2 = r.ReadLEUInt32(); }
static byte[] DecodeDXT5ToARGB(byte[] compressedData, uint width, uint height, DDSPixelFormat pixelFormat, uint mipmapCount) { return(DecodeDXTToARGB(5, compressedData, width, height, pixelFormat, mipmapCount)); }
/// <summary> /// Decodes DXT data to ARGB. /// </summary> static byte[] DecodeDXTToARGB(int DXTVersion, byte[] compressedData, uint width, uint height, DDSPixelFormat pixelFormat, uint mipmapCount) { var alphaFlag = Utils.ContainsBitFlags((int)pixelFormat.dwFlags, (int)DDSPixelFormats.AlphaPixels); var containsAlpha = alphaFlag || (pixelFormat.dwRGBBitCount == 32 && pixelFormat.dwABitMask != 0); using (var r = new UnityBinaryReader(new MemoryStream(compressedData))) { var argb = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)width, (int)height, 4)]; var mipMapWidth = (int)width; var mipMapHeight = (int)height; var baseARGBIndex = 0; for (var mipMapIndex = 0; mipMapIndex < mipmapCount; mipMapIndex++) { for (var rowIndex = 0; rowIndex < mipMapHeight; rowIndex += 4) { for (var columnIndex = 0; columnIndex < mipMapWidth; columnIndex += 4) { Color32[] colors = null; switch (DXTVersion) // Doing a switch instead of using a delegate for speed. { case 1: colors = DecodeDXT1TexelBlock(r, containsAlpha); break; case 3: colors = DecodeDXT3TexelBlock(r); break; case 5: colors = DecodeDXT5TexelBlock(r); break; default: throw new NotImplementedException($"Tried decoding a DDS file using an unsupported DXT format: DXT {DXTVersion}"); } CopyDecodedTexelBlock(colors, argb, baseARGBIndex, rowIndex, columnIndex, mipMapWidth, mipMapHeight); } } baseARGBIndex += mipMapWidth * mipMapHeight * 4; mipMapWidth /= 2; mipMapHeight /= 2; } return(argb); } }