示例#1
0
        public void Parse(Stream s)
        {
            if (s == null)
            {
                return;
            }
            BinaryReader r = new BinaryReader(s);

            info            = new RLEInfo(s);
            this.MipHeaders = new MipHeader[this.info.mipCount + 1];

            for (int i = 0; i < this.info.mipCount; i++)
            {
                MipHeaders[i] = new MipHeader
                {
                    CommandOffset = r.ReadInt32(),
                    Offset2       = r.ReadInt32(),
                    Offset3       = r.ReadInt32(),
                    Offset0       = r.ReadInt32(),
                    Offset1       = r.ReadInt32(),
                };
            }

            this.MipHeaders[this.info.mipCount] = new MipHeader
            {
                CommandOffset = MipHeaders[0].Offset2,
                Offset2       = MipHeaders[0].Offset3,
                Offset3       = MipHeaders[0].Offset0,
                Offset0       = MipHeaders[0].Offset1,
                Offset1       = (int)s.Length,
            };
            s.Position = 0;
            this.data  = r.ReadBytes((int)s.Length);
        }
        public void Parse(Stream s)
        {
            if (s == null || s.Length == 0)
            {
                this.data = new byte[0]; return;
            }
            BinaryReader r = new BinaryReader(s);

            info            = new RLEInfo(s);
            this.MipHeaders = new MipHeader[this.info.mipCount + 1];

            for (int i = 0; i < this.info.mipCount; i++)
            {
                var header = new MipHeader
                {
                    CommandOffset = r.ReadInt32(),
                    Offset2       = r.ReadInt32(),
                    Offset3       = r.ReadInt32(),
                    Offset0       = r.ReadInt32(),
                    Offset1       = r.ReadInt32(),
                };
                if (this.info.Version == RLEVersion.RLES)
                {
                    header.Offset4 = r.ReadInt32();
                }
                MipHeaders[i] = header;
            }

            this.MipHeaders[this.info.mipCount] = new MipHeader
            {
                CommandOffset = MipHeaders[0].Offset2,
                Offset2       = MipHeaders[0].Offset3,
                Offset3       = MipHeaders[0].Offset0,
                Offset0       = MipHeaders[0].Offset1,
            };

            if (this.info.Version == RLEVersion.RLES)
            {
                this.MipHeaders[this.info.mipCount].Offset1 = this.MipHeaders[0].Offset4;
                this.MipHeaders[this.info.mipCount].Offset4 = (int)s.Length;
            }
            else
            {
                this.MipHeaders[this.info.mipCount].Offset1 = (int)s.Length;
            }

            s.Position = 0;
            this.data  = r.ReadBytes((int)s.Length);
        }
        public void ImportToRLE(Stream input, RLEVersion rleVersion = RLEVersion.RLE2)
        {
            var fullOpaqueAlpha = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

            MemoryStream output = new MemoryStream();
            BinaryReader r      = new BinaryReader(input);
            BinaryWriter w      = new BinaryWriter(output);

            this.info = new RLEInfo();
            this.info.Parse(input);
            if (this.info.pixelFormat.Fourcc != FourCC.DXT5)
            {
                throw new InvalidDataException(string.Format("Not a DXT5 format DDS, read {0}", this.info.pixelFormat.Fourcc));
            }

            if (this.info.Depth == 0)
            {
                this.info.Depth = 1;
            }


            w.Write((uint)FourCC.DXT5);
            if (rleVersion == RLEVersion.RLE2)
            {
                w.Write((uint)0x32454C52);
            }
            else
            {
                w.Write((uint)0x53454C52);
            }
            w.Write((ushort)this.info.Width);
            w.Write((ushort)this.info.Height);
            w.Write((ushort)this.info.mipCount);
            w.Write((ushort)0);

            if (rleVersion == RLEVersion.RLE2)
            {
                var headerOffset = 16;
                var dataOffset   = 16 + (20 * this.info.mipCount);
                this.MipHeaders = new MipHeader[this.info.mipCount];

                using (var commandData = new MemoryStream())
                    using (var block2Data = new MemoryStream())
                        using (var block3Data = new MemoryStream())
                            using (var block0Data = new MemoryStream())
                                using (var block1Data = new MemoryStream())
                                {
                                    BinaryWriter commonDataWriter = new BinaryWriter(commandData);
                                    for (int mipIndex = 0; mipIndex < this.info.mipCount; mipIndex++)
                                    {
                                        this.MipHeaders[mipIndex] = new MipHeader()
                                        {
                                            CommandOffset = (int)commandData.Length,
                                            Offset2       = (int)block2Data.Length,
                                            Offset3       = (int)block3Data.Length,
                                            Offset0       = (int)block0Data.Length,
                                            Offset1       = (int)block1Data.Length,
                                        };

                                        var mipWidth  = Math.Max(4, this.info.Width >> mipIndex);
                                        var mipHeight = Math.Max(4, this.info.Height >> mipIndex);
                                        var mipDepth  = Math.Max(1, this.info.Depth >> mipIndex);

                                        var mipSize = Math.Max(1, (mipWidth + 3) / 4) * Math.Max(1, (mipHeight + 3) / 4) * 16;
                                        var mipData = r.ReadBytes(mipSize);

                                        for (int offset = 0; offset < mipSize;)
                                        {
                                            ushort transparentCount = 0;
                                            while (transparentCount < 0x3FFF &&
                                                   offset < mipSize &&
                                                   TestAlphaAny(mipData, offset, a => a != 0) == false)
                                            {
                                                transparentCount++;
                                                offset += 16;
                                            }

                                            if (transparentCount > 0)
                                            {
                                                transparentCount <<= 2;
                                                transparentCount  |= 0;
                                                commonDataWriter.Write(transparentCount);
                                                continue;
                                            }

                                            var    opaqueOffset = offset;
                                            ushort opaqueCount  = 0;
                                            while (opaqueCount < 0x3FFF &&
                                                   offset < mipSize &&
                                                   TestAlphaAll(mipData, offset, a => a == 0xFF) == true)
                                            {
                                                opaqueCount++;
                                                offset += 16;
                                            }

                                            if (opaqueCount > 0)
                                            {
                                                for (int i = 0; i < opaqueCount; i++, opaqueOffset += 16)
                                                {
                                                    block2Data.Write(mipData, opaqueOffset + 8, 4);
                                                    block3Data.Write(mipData, opaqueOffset + 12, 4);
                                                }

                                                opaqueCount <<= 2;
                                                opaqueCount  |= 2;
                                                commonDataWriter.Write(opaqueCount);
                                                continue;
                                            }

                                            var    translucentOffset = offset;
                                            ushort translucentCount  = 0;
                                            while (translucentCount < 0x3FFF &&
                                                   offset < mipSize &&
                                                   TestAlphaAny(mipData, offset, a => a != 0) == true &&
                                                   TestAlphaAll(mipData, offset, a => a == 0xFF) == false)
                                            {
                                                translucentCount++;
                                                offset += 16;
                                            }

                                            if (translucentCount > 0)
                                            {
                                                for (int i = 0; i < translucentCount; i++, translucentOffset += 16)
                                                {
                                                    block0Data.Write(mipData, translucentOffset + 0, 2);
                                                    block1Data.Write(mipData, translucentOffset + 2, 6);
                                                    block2Data.Write(mipData, translucentOffset + 8, 4);
                                                    block3Data.Write(mipData, translucentOffset + 12, 4);
                                                }

                                                translucentCount <<= 2;
                                                translucentCount  |= 1;
                                                commonDataWriter.Write(translucentCount);
                                                continue;
                                            }

                                            throw new NotImplementedException();
                                        }
                                    }

                                    output.Position = dataOffset;

                                    commandData.Position = 0;
                                    var commandOffset = (int)output.Position;
                                    output.Write(commandData.ToArray(), 0, (int)commandData.Length);

                                    block2Data.Position = 0;
                                    var block2Offset = (int)output.Position;
                                    output.Write(block2Data.ToArray(), 0, (int)block2Data.Length);

                                    block3Data.Position = 0;
                                    var block3Offset = (int)output.Position;
                                    output.Write(block3Data.ToArray(), 0, (int)block3Data.Length);

                                    block0Data.Position = 0;
                                    var block0Offset = (int)output.Position;
                                    output.Write(block0Data.ToArray(), 0, (int)block0Data.Length);

                                    block1Data.Position = 0;
                                    var block1Offset = (int)output.Position;
                                    output.Write(block1Data.ToArray(), 0, (int)block1Data.Length);

                                    output.Position = headerOffset;
                                    for (int i = 0; i < this.info.mipCount; i++)
                                    {
                                        var mipHeader = this.MipHeaders[i];
                                        w.Write(mipHeader.CommandOffset + commandOffset);
                                        w.Write(mipHeader.Offset2 + block2Offset);
                                        w.Write(mipHeader.Offset3 + block3Offset);
                                        w.Write(mipHeader.Offset0 + block0Offset);
                                        w.Write(mipHeader.Offset1 + block1Offset);
                                    }

                                    this.data = output.ToArray();
                                }
            }
            else
            {
                var headerOffset = 16;
                var dataOffset   = 16 + (24 * this.info.mipCount);
                this.MipHeaders = new MipHeader[this.info.mipCount];

                using (var commandData = new MemoryStream())
                    using (var block2Data = new MemoryStream())
                        using (var block3Data = new MemoryStream())
                            using (var block0Data = new MemoryStream())
                                using (var block1Data = new MemoryStream())
                                    using (var block4Data = new MemoryStream())
                                    {
                                        BinaryWriter commonDataWriter = new BinaryWriter(commandData);
                                        for (int mipIndex = 0; mipIndex < this.info.mipCount; mipIndex++)
                                        {
                                            this.MipHeaders[mipIndex] = new MipHeader()
                                            {
                                                CommandOffset = (int)commandData.Length,
                                                Offset2       = (int)block2Data.Length,
                                                Offset3       = (int)block3Data.Length,
                                                Offset0       = (int)block0Data.Length,
                                                Offset1       = (int)block1Data.Length,
                                                Offset4       = (int)block4Data.Length
                                            };

                                            var mipWidth  = Math.Max(4, this.info.Width >> mipIndex);
                                            var mipHeight = Math.Max(4, this.info.Height >> mipIndex);
                                            var mipDepth  = Math.Max(1, this.info.Depth >> mipIndex);

                                            var mipSize = Math.Max(1, (mipWidth + 3) / 4) * Math.Max(1, (mipHeight + 3) / 4) * 16;
                                            var mipData = r.ReadBytes(mipSize);

                                            for (int offset = 0; offset < mipSize;)
                                            {
                                                ushort transparentCount = 0;
                                                while (transparentCount < 0x3FFF &&
                                                       offset < mipSize &&
                                                       TestAlphaAny(mipData, offset, a => a != 0) == false)
                                                {
                                                    transparentCount++;
                                                    offset += 16;
                                                }

                                                if (transparentCount > 0)
                                                {
                                                    transparentCount <<= 2;
                                                    transparentCount  |= 0;
                                                    commonDataWriter.Write(transparentCount);
                                                    continue;
                                                }

                                                var    opaqueOffset = offset;
                                                ushort opaqueCount  = 0;
                                                while (opaqueCount < 0x3FFF &&
                                                       offset < mipSize &&
                                                       TestAlphaAll(mipData, offset, a => a == 0xFF) == true)
                                                {
                                                    opaqueCount++;
                                                    offset += 16;
                                                }

                                                if (opaqueCount > 0)
                                                {
                                                    for (int i = 0; i < opaqueCount; i++, opaqueOffset += 16)
                                                    {
                                                        block0Data.Write(mipData, opaqueOffset + 0, 2);
                                                        block1Data.Write(mipData, opaqueOffset + 2, 6);
                                                        block2Data.Write(mipData, opaqueOffset + 8, 4);
                                                        block3Data.Write(mipData, opaqueOffset + 12, 4);
                                                        // block4Data.Write(fullOpaqueAlpha, 0, 8);
                                                    }

                                                    opaqueCount <<= 2;
                                                    opaqueCount  |= 2;
                                                    commonDataWriter.Write(opaqueCount);
                                                    continue;
                                                }

                                                var    translucentOffset = offset;
                                                ushort translucentCount  = 0;
                                                while (translucentCount < 0x3FFF &&
                                                       offset < mipSize &&
                                                       TestAlphaAny(mipData, offset, a => a != 0) == true &&
                                                       TestAlphaAll(mipData, offset, a => a == 0xFF) == false)
                                                {
                                                    translucentCount++;
                                                    offset += 16;
                                                }

                                                if (translucentCount > 0)
                                                {
                                                    for (int i = 0; i < translucentCount; i++, translucentOffset += 16)
                                                    {
                                                        block0Data.Write(mipData, translucentOffset + 0, 2);
                                                        block1Data.Write(mipData, translucentOffset + 2, 6);
                                                        block2Data.Write(mipData, translucentOffset + 8, 4);
                                                        block3Data.Write(mipData, translucentOffset + 12, 4);
                                                        block4Data.Write(fullOpaqueAlpha, 0, 8);
                                                        block4Data.Write(fullOpaqueAlpha, 0, 8);
                                                    }

                                                    translucentCount <<= 2;
                                                    translucentCount  |= 1;
                                                    commonDataWriter.Write(translucentCount);
                                                    continue;
                                                }

                                                throw new NotImplementedException();
                                            }
                                        }

                                        output.Position = dataOffset;

                                        commandData.Position = 0;
                                        var commandOffset = (int)output.Position;
                                        output.Write(commandData.ToArray(), 0, (int)commandData.Length);

                                        block2Data.Position = 0;
                                        var block2Offset = (int)output.Position;
                                        output.Write(block2Data.ToArray(), 0, (int)block2Data.Length);

                                        block3Data.Position = 0;
                                        var block3Offset = (int)output.Position;
                                        output.Write(block3Data.ToArray(), 0, (int)block3Data.Length);

                                        block0Data.Position = 0;
                                        var block0Offset = (int)output.Position;
                                        output.Write(block0Data.ToArray(), 0, (int)block0Data.Length);

                                        block1Data.Position = 0;
                                        var block1Offset = (int)output.Position;
                                        output.Write(block1Data.ToArray(), 0, (int)block1Data.Length);

                                        block4Data.Position = 0;
                                        var block4Offset = (int)output.Position;
                                        output.Write(block4Data.ToArray(), 0, (int)block4Data.Length);

                                        output.Position = headerOffset;
                                        for (int i = 0; i < this.info.mipCount; i++)
                                        {
                                            var mipHeader = this.MipHeaders[i];
                                            w.Write(mipHeader.CommandOffset + commandOffset);
                                            w.Write(mipHeader.Offset2 + block2Offset);
                                            w.Write(mipHeader.Offset3 + block3Offset);
                                            w.Write(mipHeader.Offset0 + block0Offset);
                                            w.Write(mipHeader.Offset1 + block1Offset);
                                            w.Write(mipHeader.Offset4 + block4Offset);
                                        }

                                        this.data = output.ToArray();
                                    }
            }
        }