From 5dfcc3e9d073d7aa3e316a0e5518a0dfb7b957d5 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Fri, 10 Apr 2015 18:34:06 +0100 Subject: [PATCH 1/4] Convert custom map previews that are not using PixelFormat.Format32bppArgb. --- OpenRA.Game/Map/Map.cs | 9 +++++++++ OpenRA.Game/Map/MapPreview.cs | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 782c7fdbf8..b61ed70706 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -12,6 +12,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -391,8 +392,16 @@ namespace OpenRA DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex; if (Container.Exists("map.png")) + { using (var dataStream = Container.GetContent("map.png")) CustomPreview = new Bitmap(dataStream); + if (CustomPreview.PixelFormat != PixelFormat.Format32bppArgb) + { + var original = CustomPreview; + CustomPreview = original.Clone(original.Bounds(), PixelFormat.Format32bppArgb); + original.Dispose(); + } + } PostInit(); diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index fb843d1eaa..ab3bbd3402 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Drawing; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Net; @@ -155,6 +156,12 @@ namespace OpenRA SpawnPoints = spawns; CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap))); + if (CustomPreview.PixelFormat != PixelFormat.Format32bppArgb) + { + var original = CustomPreview; + CustomPreview = original.Clone(original.Bounds(), PixelFormat.Format32bppArgb); + original.Dispose(); + } } catch (Exception) { } From 7883355481cd1e7e75af27bdcb9f71f78e032330 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Fri, 10 Apr 2015 18:35:02 +0100 Subject: [PATCH 2/4] Validate PixelFormat of source bitmap argument in FastCopyIntoSprite. --- OpenRA.Game/Graphics/Util.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenRA.Game/Graphics/Util.cs b/OpenRA.Game/Graphics/Util.cs index d0b05396f0..9851fcff52 100644 --- a/OpenRA.Game/Graphics/Util.cs +++ b/OpenRA.Game/Graphics/Util.cs @@ -64,6 +64,9 @@ namespace OpenRA.Graphics public static void FastCopyIntoSprite(Sprite dest, Bitmap src) { + if (src.PixelFormat != PixelFormat.Format32bppArgb) + throw new ArgumentException("src must have a PixelFormat of Format32bppArgb", "src"); + var data = dest.Sheet.GetData(); var dataStride = dest.Sheet.Size.Width * 4; var x = dest.Bounds.Left * 4; @@ -72,7 +75,7 @@ namespace OpenRA.Graphics var height = dest.Bounds.Height; var bd = src.LockBits(src.Bounds(), - ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); + ImageLockMode.ReadWrite, src.PixelFormat); for (var row = 0; row < height; row++) Marshal.Copy(IntPtr.Add(bd.Scan0, row * bd.Stride), data, (y + row) * dataStride + x, width); src.UnlockBits(bd); From c1787a836803d8e478a81d59403ff9026eed599a Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sat, 11 Apr 2015 15:20:16 +0100 Subject: [PATCH 3/4] Don't process images with the wrong pixel format in MapCache. --- OpenRA.Game/Map/MapCache.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index 0303c32795..44bc4a9d9c 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -11,6 +11,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Net; @@ -174,6 +175,11 @@ namespace OpenRA createdPreview = true; bitmap = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true); } + else if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) + { + Log.Write("debug", "Discarding invalid map preview for {0}", p.Uid); + continue; + } // Note: this is not generally thread-safe, but it works here because: // (a) This worker is the only thread writing to this sheet From 84dffce7c16e5dd6399833837a37edc6bb379501 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sat, 11 Apr 2015 21:05:46 +0100 Subject: [PATCH 4/4] Added an extension method to clone bitmaps with a 32bbpArgb pixel format. --- OpenRA.Game/Exts.cs | 20 ++++++++++++++++++++ OpenRA.Game/Map/Map.cs | 2 +- OpenRA.Game/Map/MapPreview.cs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index b5e3a6c9de..6acf22c314 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Imaging; using System.Globalization; using System.Linq; using System.Reflection; @@ -434,6 +435,25 @@ namespace OpenRA public static Rectangle Bounds(this Bitmap b) { return new Rectangle(0, 0, b.Width, b.Height); } + public static Bitmap CloneWith32bbpArgbPixelFormat(this Bitmap original) + { + // Note: We would use original.Clone(original.Bounds(), PixelFormat.Format32bppArgb) + // but this doesn't work on mono. + var clone = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb); + try + { + using (var g = System.Drawing.Graphics.FromImage(clone)) + g.DrawImage(original, original.Bounds()); + } + catch (Exception) + { + clone.Dispose(); + throw; + } + + return clone; + } + public static int ToBits(this IEnumerable bits) { var i = 0; diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index b61ed70706..ffbcf494ba 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -398,7 +398,7 @@ namespace OpenRA if (CustomPreview.PixelFormat != PixelFormat.Format32bppArgb) { var original = CustomPreview; - CustomPreview = original.Clone(original.Bounds(), PixelFormat.Format32bppArgb); + CustomPreview = original.CloneWith32bbpArgbPixelFormat(); original.Dispose(); } } diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index ab3bbd3402..2b85004f38 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -159,7 +159,7 @@ namespace OpenRA if (CustomPreview.PixelFormat != PixelFormat.Format32bppArgb) { var original = CustomPreview; - CustomPreview = original.Clone(original.Bounds(), PixelFormat.Format32bppArgb); + CustomPreview = original.CloneWith32bbpArgbPixelFormat(); original.Dispose(); } }