From c541a0e0dc26e8a474056f71e84ff15dee73add5 Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:01:27 +0200 Subject: [PATCH] Improve HD sheet creation --- OpenRA.Game/FileFormats/Png.cs | 43 +++++++++++++------ .../DumpSequenceSheetsCommand.cs | 5 ++- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/OpenRA.Game/FileFormats/Png.cs b/OpenRA.Game/FileFormats/Png.cs index e033e2940d..8a394926e1 100644 --- a/OpenRA.Game/FileFormats/Png.cs +++ b/OpenRA.Game/FileFormats/Png.cs @@ -25,6 +25,12 @@ namespace OpenRA.FileFormats { public class Png { + public enum Compression : byte + { + BEST_COMPRESSION = Deflater.BEST_COMPRESSION, + BEST_SPEED = Deflater.BEST_SPEED, + } + static readonly byte[] Signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; public int Width { get; } @@ -256,14 +262,27 @@ namespace OpenRA.FileFormats // Convert to big endian Data = new byte[data.Length]; var stride = PixelStride; - for (var i = 0; i < width * height; i++) + var elements = width * height * stride; + var src = data.AsSpan(); + var dst = Data.AsSpan(); + if (type == SpriteFrameType.Bgra32) { - Data[stride * i] = data[stride * i + 2]; - Data[stride * i + 1] = data[stride * i + 1]; - Data[stride * i + 2] = data[stride * i + 0]; - - if (type == SpriteFrameType.Bgra32) - Data[stride * i + 3] = data[stride * i + 3]; + for (var i = 0; i < elements; i += 4) + { + dst[i + 0] = src[i + 2]; + dst[i + 1] = src[i + 1]; + dst[i + 2] = src[i + 0]; + dst[i + 3] = src[i + 3]; + } + } + else + { + for (var i = 0; i < elements; i += 3) + { + dst[i + 0] = src[i + 2]; + dst[i + 1] = src[i + 1]; + dst[i + 2] = src[i + 0]; + } } break; @@ -303,7 +322,7 @@ namespace OpenRA.FileFormats throw new InvalidDataException("Unknown pixel format"); } - static void WritePngChunk(Stream output, string type, Stream input) + static void WritePngChunk(MemoryStream output, string type, MemoryStream input) { input.Position = 0; @@ -320,7 +339,7 @@ namespace OpenRA.FileFormats output.Write(IPAddress.NetworkToHostOrder((int)crc32.Value)); } - public byte[] Save() + public byte[] Save(Compression compression = Compression.BEST_COMPRESSION) { using (var output = new MemoryStream()) { @@ -372,7 +391,7 @@ namespace OpenRA.FileFormats using (var data = new MemoryStream()) { - using (var compressed = new DeflaterOutputStream(data, new Deflater(Deflater.BEST_COMPRESSION))) + using (var compressed = new DeflaterOutputStream(data, new Deflater((int)compression))) { var rowStride = Width * PixelStride; for (var y = 0; y < Height; y++) @@ -404,9 +423,9 @@ namespace OpenRA.FileFormats } } - public void Save(string path) + public void Save(string path, Compression compression = Compression.BEST_COMPRESSION) { - File.WriteAllBytes(path, Save()); + File.WriteAllBytes(path, Save(compression)); } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs b/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs index 6efc04107c..e6337d876e 100644 --- a/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs @@ -10,6 +10,7 @@ #endregion using System; +using OpenRA.FileFormats; using OpenRA.FileSystem; using OpenRA.Graphics; @@ -56,14 +57,14 @@ namespace OpenRA.Mods.Common.UtilityCommands { var max = s == sb.Current ? (int)sb.CurrentChannel + 1 : 4; for (var i = 0; i < max; i++) - s.AsPng((TextureChannel)ChannelMasks[i], palette).Save($"{count}.{i}.png"); + s.AsPng((TextureChannel)ChannelMasks[i], palette).Save($"{count}.{i}.png", Png.Compression.BEST_SPEED); count++; } sb = sequences.SpriteCache.SheetBuilders[SheetType.BGRA]; foreach (var s in sb.AllSheets) - s.AsPng().Save($"{count++}.png"); + s.AsPng().Save($"{count++}.png", Png.Compression.BEST_SPEED); } } }