add platform-independant interface for loading Image objects from streams. add SDL backend support
SDL2# does not include anything suitable for using Streams with, so we just use System.Drawing instead for now
This commit is contained in:
parent
a914c2bcab
commit
b48a13757b
|
@ -41,6 +41,7 @@
|
||||||
<Reference Include="SDL2#">
|
<Reference Include="SDL2#">
|
||||||
<HintPath>..\Libs\SDL2#.dll</HintPath>
|
<HintPath>..\Libs\SDL2#.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
<Compile Include="CurrentOS.cs" />
|
<Compile Include="CurrentOS.cs" />
|
||||||
<Compile Include="Input\SDLKeyMapper.cs" />
|
<Compile Include="Input\SDLKeyMapper.cs" />
|
||||||
<Compile Include="SDLApplication.cs" />
|
<Compile Include="SDLApplication.cs" />
|
||||||
|
<Compile Include="Graphics\SDLBitmap.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -64,5 +66,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Input\" />
|
<Folder Include="Input\" />
|
||||||
<Folder Include="IO\" />
|
<Folder Include="IO\" />
|
||||||
|
<Folder Include="Graphics\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
125
Blarg.GameFramework.SDL2/Graphics/SDLBitmap.cs
Normal file
125
Blarg.GameFramework.SDL2/Graphics/SDLBitmap.cs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Blarg.GameFramework.Graphics
|
||||||
|
{
|
||||||
|
public class SDLBitmap : IPlatformBitmap
|
||||||
|
{
|
||||||
|
byte[] _pixels;
|
||||||
|
int _width;
|
||||||
|
int _height;
|
||||||
|
Graphics.ImageFormat _format;
|
||||||
|
|
||||||
|
public byte[] Pixels
|
||||||
|
{
|
||||||
|
get { return _pixels; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get { return _width; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Height
|
||||||
|
{
|
||||||
|
get { return _height; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graphics.ImageFormat Format
|
||||||
|
{
|
||||||
|
get { return _format; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SDLBitmap(Stream file)
|
||||||
|
{
|
||||||
|
_pixels = GetBitmap(file, out _width, out _height, out _format);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GetBitmap(Stream file, out int width, out int height, out Graphics.ImageFormat format)
|
||||||
|
{
|
||||||
|
if (file == null)
|
||||||
|
throw new ArgumentNullException("file");
|
||||||
|
|
||||||
|
using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(file))
|
||||||
|
{
|
||||||
|
int bpp = 0;
|
||||||
|
if (bitmap.PixelFormat == PixelFormat.Format32bppArgb)
|
||||||
|
{
|
||||||
|
bpp = 32;
|
||||||
|
format = Graphics.ImageFormat.RGBA;
|
||||||
|
}
|
||||||
|
else if (bitmap.PixelFormat == PixelFormat.Format24bppRgb)
|
||||||
|
{
|
||||||
|
bpp = 24;
|
||||||
|
format = Graphics.ImageFormat.RGB;
|
||||||
|
}
|
||||||
|
else if (bitmap.PixelFormat == PixelFormat.Alpha)
|
||||||
|
{
|
||||||
|
bpp = 8;
|
||||||
|
format = Graphics.ImageFormat.A;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException(String.Format("Unsupported bitmap pixel format: {0}", bitmap.PixelFormat.ToString()));
|
||||||
|
|
||||||
|
width = bitmap.Width;
|
||||||
|
height = bitmap.Height;
|
||||||
|
|
||||||
|
byte[] pixels;
|
||||||
|
|
||||||
|
var lockRegion = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
|
||||||
|
var bitmapData = bitmap.LockBits(lockRegion, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int bitmapSizeInBytes = bitmap.Width * bitmap.Height * (bpp / 8);
|
||||||
|
int expectedPitch = bitmap.Width * (bpp / 8);
|
||||||
|
int actualPitch = bitmapData.Stride;
|
||||||
|
|
||||||
|
if (expectedPitch != actualPitch)
|
||||||
|
throw new InvalidOperationException("Expected bitmap pitch mismatch. Uncaught unsupported bitmap format?");
|
||||||
|
|
||||||
|
pixels = new byte[bitmapData.Stride * bitmap.Height];
|
||||||
|
Marshal.Copy(bitmapData.Scan0, pixels, 0, bitmapSizeInBytes);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
bitmap.UnlockBits(bitmapData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: are there any cases where this should *not* be run?
|
||||||
|
SwapRgbOrdering(pixels, format);
|
||||||
|
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SwapRgbOrdering(byte[] pixels, Graphics.ImageFormat pixelFormat)
|
||||||
|
{
|
||||||
|
if (pixelFormat == Graphics.ImageFormat.A)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// assumption is that this will only ever be 3 or 4 (RGB, or RGBA)
|
||||||
|
int pixelSizeBytes;
|
||||||
|
if (pixelFormat == Graphics.ImageFormat.RGB)
|
||||||
|
pixelSizeBytes = 3;
|
||||||
|
else
|
||||||
|
pixelSizeBytes = 4;
|
||||||
|
|
||||||
|
if (pixels.Length % pixelSizeBytes != 0)
|
||||||
|
throw new InvalidDataException("Pixel data format mismatch.");
|
||||||
|
|
||||||
|
// swap R and B values for each pixel
|
||||||
|
for (int i = 0; i < pixels.Length; i += pixelSizeBytes)
|
||||||
|
{
|
||||||
|
byte r = pixels[i];
|
||||||
|
byte b = pixels[i + 2];
|
||||||
|
pixels[i] = b;
|
||||||
|
pixels[i + 2] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using SDL2;
|
using SDL2;
|
||||||
using PortableGL;
|
using PortableGL;
|
||||||
using PortableGL.SDL;
|
using PortableGL.SDL;
|
||||||
|
@ -612,6 +613,15 @@ namespace Blarg.GameFramework
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Support Functions
|
||||||
|
|
||||||
|
public override IPlatformBitmap LoadBitmap(Stream file)
|
||||||
|
{
|
||||||
|
return new SDLBitmap(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
protected override void Release()
|
protected override void Release()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using PortableGL;
|
using PortableGL;
|
||||||
using Blarg.GameFramework.Graphics;
|
using Blarg.GameFramework.Graphics;
|
||||||
using Blarg.GameFramework.Input;
|
using Blarg.GameFramework.Input;
|
||||||
|
@ -38,6 +39,8 @@ namespace Blarg.GameFramework
|
||||||
public abstract void Run(IGameApp gameApp, IPlatformConfiguration config);
|
public abstract void Run(IGameApp gameApp, IPlatformConfiguration config);
|
||||||
public abstract void Quit();
|
public abstract void Quit();
|
||||||
|
|
||||||
|
public abstract IPlatformBitmap LoadBitmap(Stream file);
|
||||||
|
|
||||||
protected void OnInit()
|
protected void OnInit()
|
||||||
{
|
{
|
||||||
Logger.Info(LOG_TAG, "Initializing application objects.");
|
Logger.Info(LOG_TAG, "Initializing application objects.");
|
||||||
|
|
|
@ -124,6 +124,8 @@
|
||||||
<Compile Include="Graphics\BuiltinShaders\Sprite2DShader.cs" />
|
<Compile Include="Graphics\BuiltinShaders\Sprite2DShader.cs" />
|
||||||
<Compile Include="Graphics\BuiltinShaders\Sprite3DShader.cs" />
|
<Compile Include="Graphics\BuiltinShaders\Sprite3DShader.cs" />
|
||||||
<Compile Include="Support\StringExtensions.cs" />
|
<Compile Include="Support\StringExtensions.cs" />
|
||||||
|
<Compile Include="Graphics\ImageFormat.cs" />
|
||||||
|
<Compile Include="Graphics\IPlatformBitmap.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
12
Blarg.GameFramework/Graphics/IPlatformBitmap.cs
Normal file
12
Blarg.GameFramework/Graphics/IPlatformBitmap.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Blarg.GameFramework.Graphics
|
||||||
|
{
|
||||||
|
public interface IPlatformBitmap
|
||||||
|
{
|
||||||
|
byte[] Pixels { get; }
|
||||||
|
int Width { get; }
|
||||||
|
int Height { get; }
|
||||||
|
ImageFormat Format { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Blarg.GameFramework.Graphics
|
namespace Blarg.GameFramework.Graphics
|
||||||
{
|
{
|
||||||
public enum ImageFormat
|
|
||||||
{
|
|
||||||
RGB,
|
|
||||||
RGBA,
|
|
||||||
A
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Image
|
public partial class Image
|
||||||
{
|
{
|
||||||
private byte[] _pixels;
|
private byte[] _pixels;
|
||||||
|
@ -47,28 +41,15 @@ namespace Blarg.GameFramework.Graphics
|
||||||
Create(source, copyX, copyY, copyWidth, copyHeight);
|
Create(source, copyX, copyY, copyWidth, copyHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image(byte[] pixels, int width, int height, ImageFormat format)
|
public Image(Stream file)
|
||||||
{
|
{
|
||||||
if (pixels == null)
|
if (file == null)
|
||||||
throw new ArgumentNullException("pixels");
|
throw new ArgumentNullException("file");
|
||||||
|
|
||||||
int bpp = 0;
|
var bitmap = Platform.Application.LoadBitmap(file);
|
||||||
if (format == ImageFormat.RGB)
|
|
||||||
bpp = 24;
|
|
||||||
else if (format == ImageFormat.RGBA)
|
|
||||||
bpp = 32;
|
|
||||||
else if (format == ImageFormat.A)
|
|
||||||
bpp = 8;
|
|
||||||
|
|
||||||
if (bpp == 0)
|
CreateBaseImage(bitmap.Width, bitmap.Height, bitmap.Format);
|
||||||
throw new ArgumentException("pixelFormat");
|
Buffer.BlockCopy(bitmap.Pixels, 0, _pixels, 0, bitmap.Pixels.Length);
|
||||||
|
|
||||||
_pixels = pixels;
|
|
||||||
Width = width;
|
|
||||||
Height = height;
|
|
||||||
BitsPerPixel = bpp;
|
|
||||||
PixelFormat = format;
|
|
||||||
Pitch = Width * (BitsPerPixel / 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateBaseImage(int width, int height, ImageFormat pixelFormat)
|
private void CreateBaseImage(int width, int height, ImageFormat pixelFormat)
|
||||||
|
|
11
Blarg.GameFramework/Graphics/ImageFormat.cs
Normal file
11
Blarg.GameFramework/Graphics/ImageFormat.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Blarg.GameFramework.Graphics
|
||||||
|
{
|
||||||
|
public enum ImageFormat
|
||||||
|
{
|
||||||
|
RGB,
|
||||||
|
RGBA,
|
||||||
|
A
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using PortableGL;
|
using PortableGL;
|
||||||
using Blarg.GameFramework.Graphics;
|
using Blarg.GameFramework.Graphics;
|
||||||
using Blarg.GameFramework.Input;
|
using Blarg.GameFramework.Input;
|
||||||
|
@ -30,6 +31,8 @@ namespace Blarg.GameFramework
|
||||||
|
|
||||||
void Run(IGameApp gameApp, IPlatformConfiguration config);
|
void Run(IGameApp gameApp, IPlatformConfiguration config);
|
||||||
void Quit();
|
void Quit();
|
||||||
|
|
||||||
|
IPlatformBitmap LoadBitmap(Stream file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue