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/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); diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 782c7fdbf8..ffbcf494ba 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.CloneWith32bbpArgbPixelFormat(); + original.Dispose(); + } + } PostInit(); 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 diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index fb843d1eaa..2b85004f38 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.CloneWith32bbpArgbPixelFormat(); + original.Dispose(); + } } catch (Exception) { }