public static (string, IDxt <IImage>) ReadDds(IFile ddsFile) { using var ddsStream = ddsFile.OpenRead(); var er = new EndianBinaryReader(ddsStream, Endianness.LittleEndian); er.AssertString("DDS "); er.AssertInt32(124); // size var flags = er.ReadInt32(); var width = er.ReadInt32(); var height = er.ReadInt32(); var pitchOrLinearSize = er.ReadInt32(); var depth = er.ReadInt32(); // TODO: Read others var mipmapCount = er.ReadInt32(); var reserved1 = er.ReadInt32s(11); // DDS_PIXELFORMAT er.AssertInt32(32); // size var pfFlags = er.ReadInt32(); var pfFourCc = er.ReadString(4); var pfRgbBitCount = er.ReadInt32(); var pfRBitMask = er.ReadInt32(); var pfGBitMask = er.ReadInt32(); var pfBBitMask = er.ReadInt32(); var pfABitMask = er.ReadInt32(); var caps1 = er.ReadInt32(); var caps2 = er.ReadInt32(); var isCubeMap = (caps2 & 0x200) != 0; var hasPositiveX = (caps2 & 0x400) != 0; var hasNegativeX = (caps2 & 0x800) != 0; var hasPositiveY = (caps2 & 0x1000) != 0; var hasNegativeY = (caps2 & 0x2000) != 0; var hasPositiveZ = (caps2 & 0x4000) != 0; var hasNegativeZ = (caps2 & 0x8000) != 0; var hasVolume = (caps2 & 0x200000) != 0; var sideCount = new[] { hasPositiveX, hasNegativeX, hasPositiveY, hasNegativeY, hasPositiveZ, hasNegativeZ }.Count(b => b); sideCount = Math.Max(1, sideCount); var queue = new Queue <CubeMapSide>(); if (hasPositiveX) { queue.Enqueue(CubeMapSide.POSITIVE_X); } if (hasNegativeX) { queue.Enqueue(CubeMapSide.NEGATIVE_X); } if (hasPositiveY) { queue.Enqueue(CubeMapSide.POSITIVE_Y); } if (hasNegativeY) { queue.Enqueue(CubeMapSide.NEGATIVE_Y); } if (hasPositiveZ) { queue.Enqueue(CubeMapSide.POSITIVE_Z); } if (hasNegativeZ) { queue.Enqueue(CubeMapSide.NEGATIVE_Z); } er.Position = 128; switch (pfFourCc) { case "q\0\0\0": { var q000Text = "a16b16g16r16"; var hdrCubeMap = new CubeMapImpl <IList <float> >(); for (var s = 0; s < sideCount; s++) { var hdrMipMap = new MipMap <IList <float> >(); for (var i = 0; i < mipmapCount; ++i) { var mmWidth = width >> i; var mmHeight = height >> i; var hdr = DecompressA16B16G16R16F(er, mmWidth, mmHeight); hdrMipMap.AddLevel( new MipMapLevel <IList <float> >(hdr, mmWidth, mmHeight)); } if (!isCubeMap) { return( q000Text, new DxtImpl <IImage>( ToneMapAndConvertHdrMipMapsToBitmap(hdrMipMap))); } var side = queue.Dequeue(); switch (side) { case CubeMapSide.POSITIVE_X: { hdrCubeMap.PositiveX = hdrMipMap; break; } case CubeMapSide.NEGATIVE_X: { hdrCubeMap.NegativeX = hdrMipMap; break; } case CubeMapSide.POSITIVE_Y: { hdrCubeMap.PositiveY = hdrMipMap; break; } case CubeMapSide.NEGATIVE_Y: { hdrCubeMap.NegativeY = hdrMipMap; break; } case CubeMapSide.POSITIVE_Z: { hdrCubeMap.PositiveZ = hdrMipMap; break; } case CubeMapSide.NEGATIVE_Z: { hdrCubeMap.NegativeZ = hdrMipMap; break; } default: throw new ArgumentOutOfRangeException(); } } return(q000Text, new DxtImpl <IImage>( ToneMapAndConvertHdrCubemapToBitmap(hdrCubeMap))); } default: { ddsStream.Position = 0; return(pfFourCc, new DxtImpl <IImage>(new DdsReader().Read(ddsStream))); } } }