コード例 #1
0
        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)));
            }
            }
        }