예제 #1
0
        public void WriteToStream(Stream stream)
        {
            Contract.Requires <FileNotLoadedException>(Loaded);
            Contract.Requires <ArgumentNullException>(stream != null);
            Contract.Requires <ArgumentException>(stream.CanWrite);
            Contract.Requires <ArgumentException>(stream.CanSeek);
            Contract.Requires <InvalidCompressionMethodException>(Compression == CompressionAlgorithm.None, "Compressing is not yet supported !");
            Contract.Requires <InvalidCompressionMethodException>(Compression == CompressionAlgorithm.None ? Versions[Version] == CompressionState.Both || Versions[Version] == CompressionState.UncompressedOnly : Versions[Version] == CompressionState.Both || Versions[Version] == CompressionState.CompressedOnly);

            var origin = stream.Position;

            using (var writer = new EndianBinaryWriter(stream, new UTF8Encoding(false, true), false, IsLittleEndian))
            {
                writer.Write('T', 'I', 'D');
                writer.Write(Version);

                stream.Seek(0x04, SeekOrigin.Current);
                writer.Write(0x80);
                writer.Write(0x01);
                writer.Write(0x01);
                writer.Write(0x20);

                stream.Seek(0x20 + origin, SeekOrigin.Begin);
                writer.Write(Filename.GetCustomLength(0x20));
                writer.Write(0x60);
                writer.Write(Width);
                writer.Write(Height);
                writer.Write(Compression == CompressionAlgorithm.None ? 0x20 : 0x00);

                // TODO : Understand and write correct data for offset 0x50
                writer.Write(0x010001);

                stream.Seek(0x04, SeekOrigin.Current);

                var bitmapData = Bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                var data       = new byte[Width * Height * 4];
                Marshal.Copy(bitmapData.Scan0, data, 0, bitmapData.Width * bitmapData.Height * 4);
                Bitmap.UnlockBits(bitmapData);

                if (Compression == CompressionAlgorithm.None)
                {
                    if (Version == 0x9A)
                    {
                    }
                    else if ((Version & 0x02) == 0x02)
                    {
                        data = BitmapArrayTools.Swap32BppColorChannels(data, 3, 2, 1, 0);
                    }
                    else
                    {
                        data = BitmapArrayTools.Swap32BppColorChannels(data, 2, 1, 0, 3);
                    }
                }
                else
                {
                    data = BitmapArrayTools.Swap32BppColorChannels(data, 2, 1, 0, 3);
                    data = Squish.CompressImage(data, Width, Height, Compression.ToSquishFlags()); // TODO : This line throws a FatalExecutionEngineError for an unknown reason
                }

                writer.Write(data.Length);
                writer.Write(0x80);
                writer.Write(Compression == CompressionAlgorithm.None ? 0x00 : 0x04);

                if (Compression == CompressionAlgorithm.Dxt1)
                {
                    writer.Write(827611204);
                }
                else if (Compression == CompressionAlgorithm.Dxt5)
                {
                    writer.Write(894720068);
                }
                else
                {
                    writer.Write(0x00);
                }

                // TODO : Understand and write correct data for offsets 0x68 and 0x78
                stream.Seek(0x78 + origin, SeekOrigin.Begin);
                writer.Write(0x101);

                stream.Seek(0x80 + origin, SeekOrigin.Begin);
                writer.Write(data);

                int fileSize = (int)stream.Position;
                stream.Seek(0x04 + origin, SeekOrigin.Begin);
                writer.Write(Compression == CompressionAlgorithm.None ? fileSize : 0x80);
            }
        }