Skip to content

Commit

Permalink
Use ImageSharp for image loading/transparency. Game runs on Linux again!
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanmoffat committed Feb 10, 2022
1 parent adc091b commit a675f12
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 51 deletions.
2 changes: 2 additions & 0 deletions EOLib.Graphics/EOLib.Graphics.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<PackageReference Include="AutomaticTypeMapper" Version="1.4.1" />
<PackageReference Include="PELoaderLib" Version="1.1.1" />
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.0.0" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions EOLib.Graphics/INativeGraphicsLoader.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Drawing;
using SixLabors.ImageSharp;

namespace EOLib.Graphics
{
public interface INativeGraphicsLoader
{
Bitmap LoadGFX(GFXTypes file, int resourceValue);
IImage LoadGFX(GFXTypes file, int resourceValue);
}
}
16 changes: 4 additions & 12 deletions EOLib.Graphics/NativeGraphicsLoader.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using AutomaticTypeMapper;
using AutomaticTypeMapper;
using SixLabors.ImageSharp;

namespace EOLib.Graphics
{
Expand All @@ -16,19 +13,14 @@ public NativeGraphicsLoader(IPEFileCollection modules)
_modules = modules;
}

public Bitmap LoadGFX(GFXTypes file, int resourceValue)
public IImage LoadGFX(GFXTypes file, int resourceValue)
{
var fileBytes = _modules[file].GetEmbeddedBitmapResourceByID(resourceValue + 100);

if (fileBytes.Length == 0)
throw new GFXLoadException(resourceValue, file);

var ms = new MemoryStream(fileBytes);

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new NotImplementedException("TODO: use cross-platform image library instead of System.Drawing");

return (Bitmap)Image.FromStream(ms);
return Image.Load(fileBytes);
}
}
}
50 changes: 13 additions & 37 deletions EOLib.Graphics/NativeGraphicsManager.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using AutomaticTypeMapper;
using Microsoft.Xna.Framework.Graphics;
using Color = System.Drawing.Color;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing;

namespace EOLib.Graphics
{
Expand All @@ -27,9 +27,6 @@ public NativeGraphicsManager(INativeGraphicsLoader gfxLoader, IGraphicsDevicePro

public Texture2D TextureFromResource(GFXTypes file, int resourceVal, bool transparent = false, bool reloadFromFile = false)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new NotImplementedException("TODO: use cross-platform image library instead of System.Drawing");

Texture2D ret;

var key = new LibraryGraphicPair((int)file, 100 + resourceVal);
Expand All @@ -51,7 +48,7 @@ public Texture2D TextureFromResource(GFXTypes file, int resourceVal, bool transp
using (var mem = new System.IO.MemoryStream())
{
using (var i = BitmapFromResource(file, resourceVal, transparent))
i.Save(mem, ImageFormat.Png);
((Image)i).Save(mem, new PngEncoder());

ret = Texture2D.FromStream(_graphicsDeviceProvider.GraphicsDevice, mem);
}
Expand All @@ -64,9 +61,9 @@ public Texture2D TextureFromResource(GFXTypes file, int resourceVal, bool transp
return ret;
}

private Bitmap BitmapFromResource(GFXTypes file, int resourceVal, bool transparent)
private IImage BitmapFromResource(GFXTypes file, int resourceVal, bool transparent)
{
var ret = _gfxLoader.LoadGFX(file, resourceVal);
var ret = (Image)_gfxLoader.LoadGFX(file, resourceVal);

if (transparent)
{
Expand All @@ -78,40 +75,19 @@ private Bitmap BitmapFromResource(GFXTypes file, int resourceVal, bool transpare
// for hats: 0x080000 is transparent
if (file == GFXTypes.FemaleHat || file == GFXTypes.MaleHat)
{
CrossPlatformMakeTransparent(ret, Color.FromArgb(0xFF, 0x08, 0x00, 0x00));
CrossPlatformMakeTransparent(ret, Color.FromArgb(0xFF, 0x00, 0x08, 0x00));
CrossPlatformMakeTransparent(ret, Color.FromArgb(0xFF, 0x00, 0x00, 0x08));
CrossPlatformMakeTransparent(ret, Color.FromRgba(0x08, 0x00, 0x00, 0xFF));
CrossPlatformMakeTransparent(ret, Color.FromRgba(0x00, 0x08, 0x00, 0xFF));
CrossPlatformMakeTransparent(ret, Color.FromRgba(0x00, 0x00, 0x08, 0xFF));
}
}

return ret;
}

private static void CrossPlatformMakeTransparent(Bitmap bmp, Color transparentColor)
private static void CrossPlatformMakeTransparent(Image bmp, Color transparentColor)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
throw new NotImplementedException("TODO: use cross-platform image library instead of System.Drawing");

bmp.MakeTransparent(transparentColor);

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// PixelFormat.32bppArgb is assumed due to the call to bmp.MakeTransparent
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

var bmpBytes = new byte[bmp.Height * bmpData.Stride];
Marshal.Copy(bmpData.Scan0, bmpBytes, 0, bmpBytes.Length);

for (int i = 0; i < bmpBytes.Length; i += 4)
{
if (bmpBytes[i] == transparentColor.R && bmpBytes[i + 1] == transparentColor.G && bmpBytes[i + 2] == transparentColor.B)
bmpBytes[i + 3] = 0;
}

Marshal.Copy(bmpBytes, 0, bmpData.Scan0, bmpBytes.Length);

bmp.UnlockBits(bmpData);
}
var brush = new RecolorBrush(transparentColor, Color.Transparent, 0.0001f);
bmp.Mutate(x => x.Clear(brush));
}

public void Dispose()
Expand Down

0 comments on commit a675f12

Please sign in to comment.