Permalink
Browse files

Removed PixelBitmapContent.

Directly copying array data. Implemented more missing functions from PixelBitmapContent.
Support for 32bit or 24 bit RBGA/RGB textures.
  • Loading branch information...
1 parent 4202f2f commit a4ab9bb0936512cbee229d1f447f55a2da8b285e @RayBatts RayBatts committed Jan 24, 2013
@@ -10,30 +10,68 @@
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
+using System.IO;
namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
{
public static class GraphicsUtil
{
- public static void ConvertBitmap(Bitmap bmp, out byte[] output)
+ public static byte[] ConvertBitmap(Bitmap bmp)
{
var bitmapData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
bmp.PixelFormat);
var length = bitmapData.Stride * bitmapData.Height;
-
- if (bitmapData.PixelFormat != PixelFormat.Format32bppArgb)
- throw new NotSupportedException("Unsupported pixel format.");
-
- output = new byte[length];
+ var output = new byte[length];
// Copy bitmap to byte[]
- // NOTE: According to http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx
- // and http://stackoverflow.com/questions/8104461/pixelformat-format32bppargb-seems-to-have-wrong-byte-order
- // Image data from any GDI based function will always come in BGR/BGRA even if the format comes in as RGBA
Marshal.Copy(bitmapData.Scan0, output, 0, length);
bmp.UnlockBits(bitmapData);
+
+ // NOTE: According to http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx
+ // and http://stackoverflow.com/questions/8104461/pixelformat-format32bppargb-seems-to-have-wrong-byte-order
+ // Image data from any GDI based function are stored in memory as BGRA/BGR, even if the format says RBGA.
+
+ switch (bitmapData.PixelFormat)
+ {
+ case PixelFormat.Format32bppPArgb:
+ BGRAtoRGBA(output);
+ break;
+
+ case PixelFormat.Format32bppRgb:
+ BGRtoRGBA(output);
+ break;
+
+ default:
+ throw new NotSupportedException("Unsupported pixel format.");
+ }
+ return output;
+ }
+
+ public static void BGRAtoRGBA(byte[] data)
+ {
+ for (var x = 0; x < data.Length; x += 4)
+ {
+ data[x] ^= data[x + 2];
+ data[x + 2] ^= data[x];
+ data[x] ^= data[x + 2];
+ }
+ }
+
+ public static void BGRtoRGBA(byte[] data)
+ {
+ var output = new byte[(int)(data.LongLength * 4.0f / 3.0f)];
+ var counter = 0;
+ for (var x = 0; x < data.Length;)
+ {
+ output[counter++] = data[x + 2];
+ output[counter++] = data[x + 1];
+ output[counter++] = data[x];
+ output[counter++] = (byte)255;
+
+ x += 3;
+ }
}
@@ -4,65 +4,116 @@
using System;
using Microsoft.Xna.Framework.Graphics;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
{
- public abstract class PixelBitmapContentBase<T> : BitmapContent where T : struct, IEquatable<T>
+ public class PixelBitmapContent<T> : BitmapContent where T : struct, IEquatable<T>
{
- internal T[,] _pixelData;
- protected SurfaceFormat _format;
+ internal T[] _pixelData;
+ protected SurfaceFormat _format = SurfaceFormat.Color;
- public virtual T GetPixel(int x, int y)
+ public PixelBitmapContent(int width, int height)
{
- if (x * y == 0 || x >= Width || y >= Height)
- throw new ArgumentOutOfRangeException("x or y");
+ Height = height;
+ Width = width;
- return _pixelData[y, x];
+ _pixelData = new T[height * width];
+
+ var counter = 0;
+ for (int y = 0; y < height; y++)
+ {
+ for (var x = 0; x < width; x++)
+ {
+ _pixelData[counter++] = new T();
+ }
+ }
}
public override byte[] GetPixelData()
{
- throw new NotImplementedException();
+ var dataSize = Width * Height * _format.Size();
+ int dataSize2 = Marshal.SizeOf(typeof(T));
+ var outputData = new byte[dataSize];
+
+ var dataHandle = GCHandle.Alloc(_pixelData, GCHandleType.Pinned);
+ var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64());
+
+ Marshal.Copy(dataPtr, outputData, 0, dataSize);
+
+ dataHandle.Free();
+
+ return outputData;
}
- public virtual T[] GetRow(int y)
+ public override void SetPixelData(byte[] sourceData)
{
- throw new NotImplementedException();
+ var dataHandle = GCHandle.Alloc(_pixelData, GCHandleType.Pinned);
+ var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64());
+
+ // Copy from the temporary buffer to the destination array
+ int dataSize = Marshal.SizeOf(typeof(T));
+
+ Marshal.Copy(sourceData, 0, dataPtr, sourceData.Length);
+
+ dataHandle.Free();
}
- protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destRegion)
+ // TODO: Docs say the value for this needs to be modifiable?
+ public T[] GetRow(int y)
{
- throw new NotImplementedException();
+ var output = new T[Width];
+
+ for (var x = 0; x < Width; x++)
+ output[x] = _pixelData[(y * Height) + x];
+
+ return output;
}
- protected override bool TryCopyTo(BitmapContent destBitmap, Rectangle sourceRegion, Rectangle destRegion)
+ /// <summary>
+ /// Gets the corresponding GPU texture format for the specified bitmap type.
+ /// </summary>
+ /// <param name="format">Format being retrieved.</param>
+ /// <returns>The GPU texture format of the bitmap type.</returns>
+ public override bool TryGetFormat(out SurfaceFormat format)
{
- throw new NotImplementedException();
+ format = SurfaceFormat.Color;
+ return true;
}
- public override bool TryGetFormat(out SurfaceFormat format)
+ public T GetPixel(int x, int y)
{
- throw new NotImplementedException();
+ return _pixelData[(y * Width) + x];
}
- public override string ToString()
+ public void SetPixel(int x, int y, T value)
{
- return base.ToString();
+ _pixelData[(y * Width) + x] = value;
}
- public override void SetPixelData(byte[] sourceData)
+ public void ReplaceColor(T originalColor, T newColor)
{
- throw new NotImplementedException();
+ for (var x = 0; x < _pixelData.Length; x++)
+ {
+ if (_pixelData[x].Equals(originalColor))
+ _pixelData[x] = newColor;
+ }
}
- public virtual void SetPixel(int x, int y, T value)
+ protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destRegion)
{
throw new NotImplementedException();
}
- public virtual void ReplaceColor(T originalColor, T newColor)
+ protected override bool TryCopyTo(BitmapContent destBitmap, Rectangle sourceRegion, Rectangle destRegion)
{
throw new NotImplementedException();
}
+
+ public override string ToString()
+ {
+ return base.ToString();
+ }
}
}
@@ -1,103 +0,0 @@
-// MonoGame - Copyright (C) The MonoGame Team
-// This file is subject to the terms and conditions defined in
-// file 'LICENSE.txt', which is part of this source code package.
-
-using System;
-using Microsoft.Xna.Framework.Graphics;
-using System.Drawing.Imaging;
-
-namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
-{
- public class PixelBitmapContent<T> : PixelBitmapContentBase<Color> where T : struct, IEquatable<T>
- {
- protected PixelBitmapContent()
- {
- }
-
- public PixelBitmapContent(int width, int height)
- {
- Height = height;
- Width = width;
-
- _pixelData = new Color[height, width];
-
- for (int y = 0; y < height; y++)
- {
- for (var x = 0; x < width; x++)
- {
- _pixelData[y, x] = new Color();
- }
- }
- }
-
- public override byte[] GetPixelData()
- {
- var pixelSize = _format.Size();
- var outputData = new byte[Width * Height * pixelSize];
-
- var index = 0;
- for (var y = 0; y < Height; y++)
- {
- for (var x = 0; x < Width; x++)
- {
- outputData[index++] = _pixelData[y, x].R;
- outputData[index++] = _pixelData[y, x].G;
- outputData[index++] = _pixelData[y, x].B;
- outputData[index++] = _pixelData[y, x].A;
- }
- }
- return outputData;
- }
-
- // TODO: Docs say the value for this needs to be modifiable?
- public override Color[] GetRow(int y)
- {
- var output = new Color[Width];
-
- for (var x = 0; x < Width; x++)
- output[x] = _pixelData[y, x];
-
- return output;
- }
-
- /// <summary>
- /// Gets the corresponding GPU texture format for the specified bitmap type.
- /// </summary>
- /// <param name="format">Format being retrieved.</param>
- /// <returns>The GPU texture format of the bitmap type.</returns>
- public override bool TryGetFormat(out SurfaceFormat format)
- {
- format = SurfaceFormat.Color;
- return true;
- }
-
- internal void SetPixelData(byte[] sourceData, PixelFormat pixelFormat)
- {
- switch (pixelFormat)
- {
- case PixelFormat.Format32bppArgb:
- _format = SurfaceFormat.Color;
- SetPixelData(sourceData);
- break;
-
- default:
- throw new NotImplementedException();
- }
- }
-
- public override void SetPixelData(byte[] sourceData)
- {
- int counter = 0;
- for (int y = 0; y < Height; y++)
- {
- for (int x = 0; x < Width; x++)
- {
- _pixelData[y, x].B = sourceData[counter++];
- _pixelData[y, x].G = sourceData[counter++];
- _pixelData[y, x].R = sourceData[counter++];
- _pixelData[y, x].A = sourceData[counter++];
- }
- }
- }
- }
-}
@@ -121,7 +121,6 @@
<Compile Include="Graphics\NodeContent.cs" />
<Compile Include="Graphics\NodeContentCollection.cs" />
<Compile Include="Graphics\PixelBitmapContent.cs" />
- <Compile Include="Graphics\PixelBitmapContentColor.cs" />
<Compile Include="Graphics\PositionCollection.cs" />
<Compile Include="Graphics\Texture2DContent.cs" />
<Compile Include="Graphics\TextureContent.cs" />
@@ -32,11 +32,10 @@ public override TextureContent Import(string filename, ContentImporterContext co
var output = new Texture2DContent();
var bmp = new Bitmap(filename);
- byte[] imageData;
- GraphicsUtil.ConvertBitmap(bmp, out imageData);
+ var imageData = GraphicsUtil.ConvertBitmap(bmp);
var bitmapContent = new PixelBitmapContent<Color>(bmp.Width, bmp.Height);
- bitmapContent.SetPixelData(imageData, bmp.PixelFormat);
+ bitmapContent.SetPixelData(imageData);
output.Faces.Add(new MipmapChain(bitmapContent));
return output;

0 comments on commit a4ab9bb

Please sign in to comment.