Gered
b48a13757b
SDL2# does not include anything suitable for using Streams with, so we just use System.Drawing instead for now
126 lines
2.9 KiB
C#
126 lines
2.9 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|