diff --git a/OpenRA.Editor/RenderUtils.cs b/OpenRA.Editor/RenderUtils.cs index f7b6871521..2d29595e8b 100644 --- a/OpenRA.Editor/RenderUtils.cs +++ b/OpenRA.Editor/RenderUtils.cs @@ -8,8 +8,10 @@ */ #endregion +using System.Collections; using System.Drawing; using System.Drawing.Imaging; +using System.Linq; using OpenRA.FileFormats; using OpenRA.Traits; @@ -17,11 +19,11 @@ namespace OpenRA.Editor { static class RenderUtils { - static Bitmap RenderShp(ShpReader shp, Palette p) + static Bitmap RenderShp(ISpriteSource shp, Palette p) { - var frame = shp[0]; + var frame = shp.Frames.First(); - var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed); + var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed); bitmap.Palette = p.AsSystemPalette(); @@ -33,9 +35,9 @@ namespace OpenRA.Editor byte* q = (byte*)data.Scan0.ToPointer(); var stride2 = data.Stride; - for (var i = 0; i < shp.Width; i++) - for (var j = 0; j < shp.Height; j++) - q[j * stride2 + i] = frame.Image[i + shp.Width * j]; + for (var i = 0; i < frame.Size.Width; i++) + for (var j = 0; j < frame.Size.Height; j++) + q[j * stride2 + i] = frame.Data[i + frame.Size.Width * j]; } bitmap.UnlockBits(data); @@ -78,10 +80,11 @@ namespace OpenRA.Editor var image = info.SpriteNames[0]; using (var s = FileSystem.OpenWithExts(image, exts)) { - var shp = new ShpReader(s); - var frame = shp[shp.ImageCount - 1]; + // TODO: Do this properly + var shp = new ShpReader(s) as ISpriteSource; + var frame = shp.Frames.Last(); - var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed); + var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed); bitmap.Palette = p.AsSystemPalette(); var data = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); @@ -91,13 +94,13 @@ namespace OpenRA.Editor byte* q = (byte*)data.Scan0.ToPointer(); var stride = data.Stride; - for (var i = 0; i < shp.Width; i++) - for (var j = 0; j < shp.Height; j++) - q[j * stride + i] = frame.Image[i + shp.Width * j]; + for (var i = 0; i < frame.Size.Width; i++) + for (var j = 0; j < frame.Size.Height; j++) + q[j * stride + i] = frame.Data[i + frame.Size.Width * j]; } bitmap.UnlockBits(data); - return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 }; + return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count() - 1 }; } } } diff --git a/OpenRA.FileFormats/Graphics/R8Reader.cs b/OpenRA.FileFormats/Graphics/R8Reader.cs index 132c48a436..de0cb8eaf3 100644 --- a/OpenRA.FileFormats/Graphics/R8Reader.cs +++ b/OpenRA.FileFormats/Graphics/R8Reader.cs @@ -12,17 +12,16 @@ using System.Collections; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; namespace OpenRA.FileFormats { - public class R8Image + class R8Image : ISpriteFrame { - public readonly Size Size; - public readonly int2 Offset; - public readonly byte[] Image; - - // Legacy variable. Can be removed when the utility command is made sensible. - public readonly Size FrameSize; + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get; private set; } + public byte[] Data { get; set; } public R8Image(Stream s) { @@ -52,7 +51,7 @@ namespace OpenRA.FileFormats // Skip alignment byte s.ReadUInt8(); - Image = s.ReadBytes(width*height); + Data = s.ReadBytes(width*height); // Ignore palette if (type == 1 && paletteOffset != 0) @@ -60,33 +59,19 @@ namespace OpenRA.FileFormats } } - public class R8Reader : IEnumerable + public class R8Reader : ISpriteSource { - readonly List headers = new List(); + readonly List frames = new List(); + public IEnumerable Frames { get { return frames.Cast(); } } - public readonly int Frames; + public readonly int ImageCount; public R8Reader(Stream stream) { while (stream.Position < stream.Length) { - headers.Add(new R8Image(stream)); - Frames++; + frames.Add(new R8Image(stream)); + ImageCount++; } } - - public R8Image this[int index] - { - get { return headers[index]; } - } - - public IEnumerator GetEnumerator() - { - return headers.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } } } diff --git a/OpenRA.FileFormats/Graphics/ShpReader.cs b/OpenRA.FileFormats/Graphics/ShpReader.cs index 0795b2696a..517d505978 100644 --- a/OpenRA.FileFormats/Graphics/ShpReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpReader.cs @@ -15,23 +15,28 @@ using System.Linq; namespace OpenRA.FileFormats { - public class ImageHeader + class ImageHeader : ISpriteFrame { - public uint Offset; + public Size Size { get; private set; } + public Size FrameSize { get { return Size; } } + public float2 Offset { get { return float2.Zero; } } + public byte[] Data { get; set; } + + public uint FileOffset; public Format Format; public uint RefOffset; public Format RefFormat; public ImageHeader RefImage; - public byte[] Image; - + // Used by ShpWriter public ImageHeader() { } - public ImageHeader( BinaryReader reader ) + public ImageHeader(BinaryReader reader, Size size) { var data = reader.ReadUInt32(); - Offset = data & 0xffffff; + Size = size; + FileOffset = data & 0xffffff; Format = (Format)(data >> 24); RefOffset = reader.ReadUInt16(); @@ -42,7 +47,7 @@ namespace OpenRA.FileFormats public void WriteTo(BinaryWriter writer) { - writer.Write(Offset | ((uint)Format << 24)); + writer.Write(FileOffset | ((uint)Format << 24)); writer.Write((ushort)RefOffset); writer.Write((ushort)RefFormat); } @@ -50,7 +55,7 @@ namespace OpenRA.FileFormats public enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 } - public class ShpReader + public class ShpReader : ISpriteSource { public readonly int ImageCount; public readonly ushort Width; @@ -59,6 +64,7 @@ namespace OpenRA.FileFormats public Size Size { get { return new Size(Width, Height); } } readonly List headers = new List(); + public IEnumerable Frames { get { return headers.Cast(); } } int recurseDepth = 0; @@ -73,13 +79,14 @@ namespace OpenRA.FileFormats Height = reader.ReadUInt16(); reader.ReadUInt32(); + var size = new Size(Width, Height); for (int i = 0 ; i < ImageCount ; i++) - headers.Add(new ImageHeader(reader)); + headers.Add(new ImageHeader(reader, size)); - new ImageHeader(reader); // end-of-file header - new ImageHeader(reader); // all-zeroes header + new ImageHeader(reader, size); // end-of-file header + new ImageHeader(reader, size); // all-zeroes header - var offsets = headers.ToDictionary(h => h.Offset, h =>h); + var offsets = headers.ToDictionary(h => h.FileOffset, h =>h); for (int i = 0 ; i < ImageCount ; i++) { @@ -89,7 +96,7 @@ namespace OpenRA.FileFormats else if (h.Format == Format.Format40) if (!offsets.TryGetValue(h.RefOffset, out h.RefImage)) - throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset)); + throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset)); } foreach (ImageHeader h in headers) @@ -97,11 +104,6 @@ namespace OpenRA.FileFormats } } - public ImageHeader this[int index] - { - get { return headers[index]; } - } - void Decompress(Stream stream, ImageHeader h) { if (recurseDepth > ImageCount) @@ -112,22 +114,22 @@ namespace OpenRA.FileFormats case Format.Format20: case Format.Format40: { - if (h.RefImage.Image == null) + if (h.RefImage.Data == null) { ++recurseDepth; Decompress(stream, h.RefImage); --recurseDepth; } - h.Image = CopyImageData(h.RefImage.Image); - Format40.DecodeInto(ReadCompressedData(stream, h), h.Image); + h.Data = CopyImageData(h.RefImage.Data); + Format40.DecodeInto(ReadCompressedData(stream, h), h.Data); break; } case Format.Format80: { var imageBytes = new byte[Width * Height]; Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes); - h.Image = imageBytes; + h.Data = imageBytes; break; } default: @@ -137,7 +139,7 @@ namespace OpenRA.FileFormats static byte[] ReadCompressedData(Stream stream, ImageHeader h) { - stream.Position = h.Offset; + stream.Position = h.FileOffset; // TODO: Actually, far too big. There's no length field with the correct length though :( var compressedLength = (int)(stream.Length - stream.Position); @@ -156,12 +158,45 @@ namespace OpenRA.FileFormats return imageData; } - public IEnumerable Frames { get { return headers; } } - public static ShpReader Load(string filename) { using (var s = File.OpenRead(filename)) return new ShpReader(s); } + + 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, FileOffset = (uint)dataOffset }; + dataOffset += f.Length; + + ih.WriteTo(bw); + } + + var eof = new ImageHeader { FileOffset = (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/Graphics/ShpTSReader.cs b/OpenRA.FileFormats/Graphics/ShpTSReader.cs index 66f8e40d6b..2aaaf2ac7f 100644 --- a/OpenRA.FileFormats/Graphics/ShpTSReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpTSReader.cs @@ -15,17 +15,17 @@ using System.Linq; namespace OpenRA.FileFormats { - public class TSImageHeader + class FrameHeader : ISpriteFrame { - public readonly Size Size; - public readonly float2 Offset; + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get; private set; } + public byte[] Data { get; set; } public readonly uint FileOffset; public readonly byte Format; - public byte[] Image; - - public TSImageHeader(Stream stream, Size frameSize) + public FrameHeader(Stream stream, Size frameSize) { var x = stream.ReadUInt16(); var y = stream.ReadUInt16(); @@ -34,6 +34,7 @@ namespace OpenRA.FileFormats Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height)); Size = new Size(width, height); + FrameSize = frameSize; Format = stream.ReadUInt8(); stream.Position += 11; @@ -41,13 +42,13 @@ namespace OpenRA.FileFormats } } - public class ShpTSReader + public class ShpTSReader : ISpriteSource { public readonly int ImageCount; public readonly Size Size; - readonly List frames = new List(); - public IEnumerable Frames { get { return frames; } } + readonly List frames = new List(); + public IEnumerable Frames { get { return frames.Cast(); } } public ShpTSReader(Stream stream) { @@ -58,7 +59,7 @@ namespace OpenRA.FileFormats ImageCount = stream.ReadUInt16(); for (var i = 0; i < ImageCount; i++) - frames.Add(new TSImageHeader(stream, Size)); + frames.Add(new FrameHeader(stream, Size)); for (var i = 0; i < ImageCount; i++) { @@ -70,23 +71,23 @@ namespace OpenRA.FileFormats // Uncompressed if (f.Format == 1 || f.Format == 0) - f.Image = stream.ReadBytes(f.Size.Width * f.Size.Height); + f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height); // Uncompressed scanlines else if (f.Format == 2) { - f.Image = new byte[f.Size.Width * f.Size.Height]; + f.Data = new byte[f.Size.Width * f.Size.Height]; for (var j = 0; j < f.Size.Height; j++) { var length = stream.ReadUInt16() - 2; - stream.Read(f.Image, f.Size.Width * j, length); + stream.Read(f.Data, f.Size.Width * j, length); } } // RLE-zero compressed scanlines else if (f.Format == 3) { - f.Image = new byte[f.Size.Width * f.Size.Height]; + f.Data = new byte[f.Size.Width * f.Size.Height]; for (var j = 0; j < f.Size.Height; j++) { @@ -103,7 +104,7 @@ namespace OpenRA.FileFormats length--; } else - f.Image[k++] = b; + f.Data[k++] = b; } } } diff --git a/OpenRA.FileFormats/Graphics/ShpWriter.cs b/OpenRA.FileFormats/Graphics/ShpWriter.cs deleted file mode 100644 index 9475f02c68..0000000000 --- a/OpenRA.FileFormats/Graphics/ShpWriter.cs +++ /dev/null @@ -1,56 +0,0 @@ -#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.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 { 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/Graphics/SpriteSource.cs b/OpenRA.FileFormats/Graphics/SpriteSource.cs new file mode 100644 index 0000000000..426273c0ac --- /dev/null +++ b/OpenRA.FileFormats/Graphics/SpriteSource.cs @@ -0,0 +1,188 @@ +#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.Generic; +using System.Drawing; +using System.IO; +using System.Linq; + +namespace OpenRA.FileFormats +{ + public interface ISpriteFrame + { + Size Size { get; } + Size FrameSize { get; } + float2 Offset { get; } + byte[] Data { get; } + } + + public interface ISpriteSource + { + IEnumerable Frames { get; } + } + + public enum SpriteType { Unknown, ShpTD, ShpTS, TmpTD, TmpRA, R8 } + public static class SpriteSource + { + static bool IsTmpRA(Stream s) + { + var start = s.Position; + + s.Position += 20; + var a = s.ReadUInt32(); + s.Position += 2; + var b = s.ReadUInt16(); + + s.Position = start; + return a == 0 && b == 0x2c73; + } + + static bool IsTmpTD(Stream s) + { + var start = s.Position; + + s.Position += 16; + var a = s.ReadUInt32(); + var b = s.ReadUInt32(); + + s.Position = start; + return a == 0 && b == 0x0D1AFFFF; + } + + static bool IsShpTS(Stream s) + { + var start = s.Position; + + // First word is zero + if (s.ReadUInt16() != 0) + { + s.Position = start; + return false; + } + + // Sanity Check the image count + s.Position += 4; + var imageCount = s.ReadUInt16(); + if (s.Position + 24 * imageCount > s.Length) + { + s.Position = start; + return false; + } + + // Check the size and format flag + // Some files define bogus frames, so loop until we find a valid one + s.Position += 4; + ushort w, h, f = 0; + byte type; + do + { + w = s.ReadUInt16(); + h = s.ReadUInt16(); + type = s.ReadUInt8(); + } + while (w == 0 && h == 0 && f++ < imageCount); + + s.Position = start; + return type < 4; + } + + static bool IsShpTD(Stream s) + { + var start = s.Position; + + // First word is the image count + var imageCount = s.ReadUInt16(); + if (imageCount == 0) + { + s.Position = start; + return false; + } + + // Last offset should point to the end of file + var finalOffset = start + 14 + 8 * imageCount; + if (finalOffset > s.Length) + { + s.Position = start; + return false; + } + + s.Position = finalOffset; + var eof = s.ReadUInt32(); + if (eof != s.Length) + { + s.Position = start; + return false; + } + + // Check the format flag on the first frame + s.Position = start + 17; + var b = s.ReadUInt8(); + + s.Position = start; + return b == 0x20 || b == 0x40 || b == 0x80; + } + + static bool IsR8(Stream s) + { + var start = s.Position; + + // First byte is nonzero + if (s.ReadUInt8() == 0) + { + s.Position = start; + return false; + } + + // Check the format of the first frame + s.Position = start + 25; + var d = s.ReadUInt8(); + + s.Position = start; + return d == 8; + } + + public static SpriteType DetectSpriteType(Stream s) + { + if (IsShpTD(s)) + return SpriteType.ShpTD; + + if (IsShpTS(s)) + return SpriteType.ShpTS; + + if (IsR8(s)) + return SpriteType.R8; + + if (IsTmpRA(s)) + return SpriteType.TmpRA; + + if (IsTmpTD(s)) + return SpriteType.TmpTD; + + return SpriteType.Unknown; + } + + public static ISpriteSource LoadSpriteSource(Stream s, string filename) + { + var type = DetectSpriteType(s); + switch (type) + { + case SpriteType.ShpTD: + return new ShpReader(s); + case SpriteType.ShpTS: + return new ShpTSReader(s); + case SpriteType.R8: + return new R8Reader(s); + case SpriteType.Unknown: + default: + throw new InvalidDataException(filename + " is not a valid sprite file"); + } + } + } +} diff --git a/OpenRA.FileFormats/Graphics/TileSetRenderer.cs b/OpenRA.FileFormats/Graphics/TileSetRenderer.cs index 98c7459438..e33462afd1 100644 --- a/OpenRA.FileFormats/Graphics/TileSetRenderer.cs +++ b/OpenRA.FileFormats/Graphics/TileSetRenderer.cs @@ -21,14 +21,13 @@ namespace OpenRA.FileFormats Dictionary> templates; public Size TileSize; - List LoadTemplate(string filename, string[] exts, Cache r8cache, int[] frames) + List LoadTemplate(string filename, string[] exts, Cache r8cache, int[] frames) { if (exts.Contains(".R8") && FileSystem.Exists(filename + ".R8")) { var data = new List(); - foreach (var f in frames) - data.Add(f >= 0 ? r8cache[filename][f].Image : null); + data.Add(f >= 0 ? r8cache[filename][f].Data : null); return data; } @@ -43,7 +42,7 @@ namespace OpenRA.FileFormats this.TileSize = tileSize; templates = new Dictionary>(); - var r8cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8"))); + var r8cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")).Frames.ToArray()); foreach (var t in TileSet.Templates) templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, r8cache, t.Value.Frames)); } diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index f8f42f2b1c..4f675cf4fd 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -95,7 +95,6 @@ - @@ -153,6 +152,7 @@ + diff --git a/OpenRA.Game/Graphics/SheetBuilder.cs b/OpenRA.Game/Graphics/SheetBuilder.cs index 06a479c5f4..0cee8661ef 100644 --- a/OpenRA.Game/Graphics/SheetBuilder.cs +++ b/OpenRA.Game/Graphics/SheetBuilder.cs @@ -10,6 +10,7 @@ using System; using System.Drawing; +using OpenRA.FileFormats; using OpenRA.FileFormats.Graphics; namespace OpenRA.Graphics @@ -52,6 +53,7 @@ namespace OpenRA.Graphics this.allocateSheet = allocateSheet; } + public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, frame.Offset); } public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); } public Sprite Add(byte[] src, Size size, float2 spriteOffset) { diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index c046f4f985..ad34831633 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -16,41 +16,25 @@ namespace OpenRA.Graphics { public class SpriteLoader { + readonly SheetBuilder SheetBuilder; + readonly Cache sprites; + readonly string[] exts; + public SpriteLoader(string[] exts, SheetBuilder sheetBuilder) { SheetBuilder = sheetBuilder; // Include extension-less version this.exts = exts.Append("").ToArray(); - sprites = new Cache(LoadSprites); + sprites = new Cache(CacheSpriteFrames); } - readonly SheetBuilder SheetBuilder; - readonly Cache sprites; - readonly string[] exts; - - Sprite[] LoadSprites(string filename) + Sprite[] CacheSpriteFrames(string filename) { - // TODO: Cleanly abstract file type detection - if (filename.ToLower().EndsWith("r8")) - { - var r8 = new R8Reader(FileSystem.OpenWithExts(filename, exts)); - return r8.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray(); - } - - BinaryReader reader = new BinaryReader(FileSystem.OpenWithExts(filename, exts)); - - var ImageCount = reader.ReadUInt16(); - if (ImageCount == 0) - { - var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts)); - return shp.Frames.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray(); - } - else - { - var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts)); - return shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray(); - } + var stream = FileSystem.OpenWithExts(filename, exts); + return SpriteSource.LoadSpriteSource(stream, filename).Frames + .Select(a => SheetBuilder.Add(a)) + .ToArray(); } public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; } diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index 48bfc1451f..b0e29c7a50 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -22,7 +22,7 @@ namespace OpenRA.Graphics Dictionary templates; Sprite missingTile; - Sprite[] LoadTemplate(string filename, string[] exts, Cache r8Cache, int[] frames) + Sprite[] LoadTemplate(string filename, string[] exts, Cache r8Cache, int[] frames) { if (exts.Contains(".R8") && FileSystem.Exists(filename+".R8")) { @@ -32,7 +32,7 @@ namespace OpenRA.Graphics return null; var image = r8Cache[filename][f]; - return sheetBuilder.Add(image.Image, new Size(image.Size.Width, image.Size.Height)); + return sheetBuilder.Add(image.Data, new Size(image.Size.Width, image.Size.Height)); }).ToArray(); } @@ -57,7 +57,7 @@ namespace OpenRA.Graphics return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize)); }; - var r8Cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8"))); + var r8Cache = new Cache(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")).Frames.ToArray()); templates = new Dictionary(); sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); foreach (var t in tileset.Templates) diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 9d738ef85d..7355003fc1 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -52,7 +52,7 @@ namespace OpenRA.Utility throw new InvalidOperationException("Bogus width; not a whole number of frames"); using (var destStream = File.Create(dest)) - ShpWriter.Write(destStream, width, srcImage.Height, + ShpReader.Write(destStream, width, srcImage.Height, srcImage.ToFrames(width)); Console.WriteLine(dest + " saved."); @@ -104,7 +104,7 @@ namespace OpenRA.Utility PixelFormat.Format8bppIndexed); for (var i = 0; i < bitmap.Height; i++) - Marshal.Copy(frame.Image, i * srcImage.Width, + Marshal.Copy(frame.Data, i * srcImage.Width, new IntPtr(data.Scan0.ToInt64() + i * data.Stride), srcImage.Width); x += srcImage.Width; @@ -133,12 +133,11 @@ namespace OpenRA.Utility var filename = args[5]; var frameCount = endFrame - startFrame; - var frame = srcImage[startFrame]; + // TODO: this has always been a hack + var frame = srcImage.Frames.ToArray()[startFrame]; var bitmap = new Bitmap(frame.FrameSize.Width * frameCount, frame.FrameSize.Height, PixelFormat.Format8bppIndexed); bitmap.Palette = palette.AsSystemPalette(); - frame = srcImage[startFrame]; - if (args.Contains("--tileset")) { int f = 0; @@ -152,13 +151,13 @@ namespace OpenRA.Utility if (h * 20 + w < frameCount) { Console.WriteLine(f); - frame = srcImage[f]; + frame = srcImage.Frames.ToArray()[startFrame]; var data = tileset.LockBits(new Rectangle(w * frame.Size.Width, h * frame.Size.Height, frame.Size.Width, frame.Size.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); for (var i = 0; i < frame.Size.Height; i++) - Marshal.Copy(frame.Image, i * frame.Size.Width, + Marshal.Copy(frame.Data, i * frame.Size.Width, new IntPtr(data.Scan0.ToInt64() + i * data.Stride), frame.Size.Width); tileset.UnlockBits(data); @@ -219,7 +218,7 @@ namespace OpenRA.Utility throw new InvalidOperationException("All the frames must be the same size to convert from Dune2 to RA"); using (var destStream = File.Create(dest)) - ShpWriter.Write(destStream, size.Width, size.Height, + ShpReader.Write(destStream, size.Width, size.Height, srcImage.Select(im => im.Image)); } @@ -300,8 +299,8 @@ namespace OpenRA.Utility var srcImage = ShpReader.Load(args[3]); using (var destStream = File.Create(args[4])) - ShpWriter.Write(destStream, srcImage.Width, srcImage.Height, - srcImage.Frames.Select(im => im.Image.Select(px => (byte)remap[px]).ToArray())); + ShpReader.Write(destStream, srcImage.Width, srcImage.Height, + srcImage.Frames.Select(im => im.Data.Select(px => (byte)remap[px]).ToArray())); } public static void TransposeShp(string[] args) @@ -323,8 +322,8 @@ namespace OpenRA.Utility } using (var destStream = File.Create(args[2])) - ShpWriter.Write(destStream, srcImage.Width, srcImage.Height, - destFrames.Select(f => f.Image)); + ShpReader.Write(destStream, srcImage.Width, srcImage.Height, + destFrames.Select(f => f.Data)); } static string FriendlyTypeName(Type t)