Beispiel #1
0
        public void LoadFromStream(Stream stream)
        {
            Contract.Requires <ArgumentNullException>(stream != null);
            Contract.Requires(stream.CanRead);
            Contract.Requires(stream.CanSeek);
            Contract.Requires(stream.Length >= 0x80); // Header Size, Minimum Required

            var origin = stream.Position;

            if (stream.ReadByte() != 0x54 || stream.ReadByte() != 0x49 || stream.ReadByte() != 0x44)
            {
                throw new InvalidDataException("This isn't a TID file.");
            }

            var version = (byte)stream.ReadByte();

            if (!Versions.ContainsKey(version))
            {
                throw new InvalidVersionException($"{version} isn't a valid version that can be read.");
            }

            using (var reader = new EndianBinaryReader(stream, Encoding.UTF8, true, (version & 0x01) == 0))
            {
                stream.Seek(0x20 + origin, SeekOrigin.Begin);
                var filename = reader.ReadBytes(32);

                stream.Seek(0x44 + origin, SeekOrigin.Begin);
                var width  = reader.ReadInt32();
                var height = reader.ReadInt32();

                stream.Seek(0x58 + origin, SeekOrigin.Begin);
                var dataLength = reader.ReadInt32();

                stream.Seek(0x64 + origin, SeekOrigin.Begin);
                int compressionValue = reader.ReadInt32();
                if (!Enum.IsDefined(typeof(CompressionAlgorithm), compressionValue))
                {
                    throw new InvalidCompressionMethodException($"{compressionValue} represents an incorrect or unknown compression algorithm.");
                }
                CompressionAlgorithm compression = (CompressionAlgorithm)compressionValue;

                if (stream.Length < 0x80 + dataLength)
                {
                    throw new EndOfStreamException();
                }

                stream.Seek(0x80 + origin, SeekOrigin.Begin);
                byte[] data;
                if (version == 0x9A)
                {
                    data = reader.ReadBytes(width * height * 4);
                }
                else
                {
                    data = reader.ReadBytes(dataLength);
                }

                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 = Squish.DecompressImage(data, width, height, compression.ToSquishFlags());
                    data = BitmapArrayTools.Swap32BppColorChannels(data, 2, 1, 0, 3);
                }

                if (compression == CompressionAlgorithm.Dxt1)
                {
                    data = BitmapArrayTools.Fill32BppAlpha(data, 0, 0xFF);
                }

                var bitmap     = new Bitmap(width, height, PixelFormat.Format32bppArgb);
                var bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                Marshal.Copy(data, 0, bitmapData.Scan0, data.Length);
                bitmap.UnlockBits(bitmapData);

                Bitmap      = bitmap;
                Filename    = filename;
                Compression = compression;
                Version     = version;

                Loaded = true;
            }
        }