diff --git a/OpenRA.FileFormats/Exts.cs b/OpenRA.FileFormats/Exts.cs index 916e458336..2b09647e30 100755 --- a/OpenRA.FileFormats/Exts.cs +++ b/OpenRA.FileFormats/Exts.cs @@ -10,10 +10,10 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.IO; using System.Linq; using System.Reflection; -using System.Drawing; namespace OpenRA { diff --git a/OpenRA.FileFormats/FileFormats/Format80.cs b/OpenRA.FileFormats/FileFormats/Format80.cs index a48bc23ece..74be6edd04 100644 --- a/OpenRA.FileFormats/FileFormats/Format80.cs +++ b/OpenRA.FileFormats/FileFormats/Format80.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.IO; namespace OpenRA.FileFormats { @@ -124,24 +125,24 @@ namespace OpenRA.FileFormats } } - public static int EncodeInto(byte[] src, byte[] dest) + public static byte[] Encode(byte[] src) { /* quick & dirty format80 encoder -- only uses raw copy operator, terminated with a zero-run. */ /* this does not produce good compression, but it's valid format80 */ - var destIndex = 0; var ctx = new FastByteReader(src); + var ms = new MemoryStream(); do { var len = Math.Min(ctx.Remaining(), 0x3F); - dest[destIndex++] = (byte)(0x80 | len); - if (len > 0) - ctx.CopyTo(dest, destIndex, len); + ms.WriteByte((byte)(0x80 | len)); + while (len-- > 0) + ms.WriteByte(ctx.ReadByte()); } while (!ctx.Done()); - return destIndex; + return ms.ToArray(); } } } diff --git a/OpenRA.FileFormats/Graphics/ShpReader.cs b/OpenRA.FileFormats/Graphics/ShpReader.cs index c41cd33c08..e734d42b98 100644 --- a/OpenRA.FileFormats/Graphics/ShpReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpReader.cs @@ -26,6 +26,8 @@ namespace OpenRA.FileFormats public byte[] Image; + public ImageHeader() { } + public ImageHeader( BinaryReader reader ) { Offset = reader.ReadUInt32(); @@ -35,6 +37,15 @@ namespace OpenRA.FileFormats RefOffset = reader.ReadUInt16(); RefFormat = (Format)reader.ReadUInt16(); } + + public static readonly int SizeOnDisk = 8; + + public void WriteTo(BinaryWriter writer) + { + writer.Write(Offset | ((uint)Format << 24)); + writer.Write((ushort)RefOffset); + writer.Write((ushort)RefFormat); + } } public enum Format diff --git a/OpenRA.FileFormats/Graphics/ShpWriter.cs b/OpenRA.FileFormats/Graphics/ShpWriter.cs new file mode 100644 index 0000000000..11e5ec5a94 --- /dev/null +++ b/OpenRA.FileFormats/Graphics/ShpWriter.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace OpenRA.FileFormats.Graphics +{ + // format80-only SHP writer + + public static class ShpWriter + { + public static void Write(Stream s, int width, int height, IEnumerable frames) + { + var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray(); + + // note: end-of-file and all-zeroes headers + var dataOffset = 14 + (compressedFrames.Length + 2) * ImageHeader.SizeOnDisk; + + using (var bw = new BinaryWriter(s)) + { + bw.Write((ushort)compressedFrames.Length); + bw.Write((ushort)0); // unused + bw.Write((ushort)0); // unused + bw.Write((ushort)width); + bw.Write((ushort)height); + bw.Write((uint)0); // unused + + foreach (var f in compressedFrames) + { + var ih = new ImageHeader { Format = Format.Format80, Offset = (uint)dataOffset }; + dataOffset += f.Length; + + ih.WriteTo(bw); + } + + var eof = new ImageHeader { Format = Format.Format80, Offset = (uint)dataOffset }; + eof.WriteTo(bw); + + var allZeroes = new ImageHeader { }; + allZeroes.WriteTo(bw); + + foreach (var f in compressedFrames) + bw.Write(f); + } + } + } +} diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 6b27141718..5955859895 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -66,6 +66,7 @@ +