#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System.Collections; using System.Collections.Generic; using System.Drawing; using System.IO; namespace OpenRA.FileFormats { public enum Dune2ImageFlags : int { F80_F2 = 0, F2 = 2, L16_F80_F2_1 = 1, L16_F80_F2_2 = 3, Ln_F80_F2 = 5 } public class Dune2ImageHeader { public readonly Dune2ImageFlags Flags; public readonly int Width; public readonly int Height; public readonly int Slices; public readonly int FileSize; public readonly int DataSize; public readonly byte[] LookupTable; public byte[] Image; public Dune2ImageHeader(Stream s) { Flags = (Dune2ImageFlags)s.ReadUInt16(); Slices = s.ReadUInt8(); Width = s.ReadUInt16(); Height = s.ReadUInt8(); FileSize = s.ReadUInt16(); DataSize = s.ReadUInt16(); if (Flags == Dune2ImageFlags.L16_F80_F2_1 || Flags == Dune2ImageFlags.L16_F80_F2_2 || Flags == Dune2ImageFlags.Ln_F80_F2) { int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16; LookupTable = new byte[n]; for (int i = 0; i < n; i++) LookupTable[i] = s.ReadUInt8(); } else { LookupTable = new byte[256]; for (int i = 0; i < 256; i++) LookupTable[i] = (byte)i; LookupTable[1] = 0x7f; LookupTable[2] = 0x7e; LookupTable[3] = 0x7d; LookupTable[4] = 0x7c; } } public Size Size { get { return new Size(Width, Height); } } } public class Dune2ShpReader : IEnumerable { public readonly int ImageCount; List headers = new List(); public Dune2ShpReader(Stream s) { ImageCount = s.ReadUInt16(); //Last offset is pointer to end of file. uint[] offsets = new uint[ImageCount + 1]; uint temp = s.ReadUInt32(); //If fourth byte in file is non-zero, the offsets are two bytes each. bool twoByteOffsets = (temp & 0xFF0000) > 0; if (twoByteOffsets) { offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes offsets[1] = (temp & 0xFFFF) + 2; } else offsets[0] = temp + 2; for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++) offsets[i] = (twoByteOffsets ? s.ReadUInt16() : s.ReadUInt32()) + 2; for (int i = 0; i < ImageCount; i++) { s.Seek(offsets[i], SeekOrigin.Begin); Dune2ImageHeader header = new Dune2ImageHeader(s); byte[] imgData = s.ReadBytes(header.FileSize); header.Image = new byte[header.Height * header.Width]; //Decode image data if (header.Flags != Dune2ImageFlags.F2) { byte[] tempData = new byte[header.DataSize]; Format80.DecodeInto(imgData, tempData); Format2.DecodeInto(tempData, header.Image); } else Format2.DecodeInto(imgData, header.Image); //Lookup values in lookup table if (header.LookupTable != null) for (int j = 0; j < header.Image.Length; j++) header.Image[j] = header.LookupTable[header.Image[j]]; headers.Add(header); } } public Dune2ImageHeader this[int index] { get { return headers[index]; } } public IEnumerator GetEnumerator() { return headers.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }