diff --git a/Blocks/BlockInfo.Optimised.cs b/Blocks/BlockInfo.Optimised.cs
index 1fde09df8..b75217f8a 100644
--- a/Blocks/BlockInfo.Optimised.cs
+++ b/Blocks/BlockInfo.Optimised.cs
@@ -164,11 +164,12 @@ namespace ClassicalSharp {
}
}
- static void MovePortion( int srcX, int srcY, int destX, int destY, FastBitmap src, int size ) {
+ unsafe static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, int size ) {
for( int y = 0; y < size; y++ ) {
+ int* srcRow = src.GetRowPtr( srcY + y );
+ int* dstRow = src.GetRowPtr( dstY + y );
for( int x = 0; x < size; x++ ) {
- int col = src.GetPixel( srcX + x, srcY + y );
- src.SetPixel( destX + x, destY + y, col );
+ dstRow[dstX + x] = srcRow[srcX + x];
}
}
}
diff --git a/FastBitmap.cs b/FastBitmap.cs
index 5e606a742..7944bc996 100644
--- a/FastBitmap.cs
+++ b/FastBitmap.cs
@@ -6,33 +6,8 @@ namespace ClassicalSharp {
/// Represents a wrapper around a bitmap. Provides
/// a fast implementation for getting and setting pixels in that bitmap.
- public class FastBitmap : IDisposable {
-
- unsafe abstract class PixelAccessor {
- public byte* scan0;
- public int stride;
-
- public abstract int GetPixel( int x, int y );
-
- public abstract void SetPixel( int x, int y, int col );
- }
-
- unsafe class _32bppARGBAccessor : PixelAccessor {
-
- public override int GetPixel( int x, int y ) {
- // row + ( x << 2 ) points to the B part of the pixel at (x, bottomY/row)
- // casting to Int* then returning the value is a cheap way of
- // doing the bitwise arithmetic that would otherwise be used.
- // TODO: Does this work with big-endian systems? I don't know.
- int* row = (int*)( scan0 + ( y * stride ) );
- return row[x]; // b g r a
- }
-
- public override void SetPixel( int x, int y, int col ) {
- int* row = (int*)( scan0 + ( y * stride ) );
- row[x] = col;
- }
- }
+ /// Only supports 32 bit RGBA pixel format.
+ public unsafe class FastBitmap : IDisposable {
/// Constructs a new FastBitmap wrapped around the specified Bitmap.
/// Bitmap which is wrapped.
@@ -47,7 +22,8 @@ namespace ClassicalSharp {
public Bitmap Bitmap;
BitmapData data;
- PixelAccessor accessor;
+ byte* scan0;
+ int stride;
public bool IsLocked {
get { return data != null; }
@@ -58,7 +34,7 @@ namespace ClassicalSharp {
get { return data.Scan0; }
}
- /// Gets the stride width/scan width of the bitmap.
+ /// Gets the stride width/scan width of the bitmap.
/// (i.e. the actual size of each scanline, including padding)
public int Stride {
get { return data.Stride; }
@@ -74,26 +50,23 @@ namespace ClassicalSharp {
get { return data.Height; }
}
- /// Locks the wrapped bitmap into system memory,
+ /// Locks the wrapped bitmap into system memory,
/// so that fast get/set pixel operations can be performed.
- /// Only 24 and 32 bit bitmap formats are supported.
- public unsafe void LockBits() {
+ public void LockBits() {
if( Bitmap == null ) throw new InvalidOperationException( "Bmp is null." );
if( data != null ) {
Bitmap.UnlockBits( data );
}
PixelFormat format = Bitmap.PixelFormat;
- if( format == PixelFormat.Format32bppArgb ) {
- accessor = new _32bppARGBAccessor();
- } else {
+ if( format != PixelFormat.Format32bppArgb ) {
throw new NotSupportedException( "Unsupported bitmap pixel format:" + format );
}
Rectangle rec = new Rectangle( 0, 0, Bitmap.Width, Bitmap.Height );
data = Bitmap.LockBits( rec, ImageLockMode.ReadWrite, format );
- accessor.scan0 = (byte*)data.Scan0;
- accessor.stride = data.Stride;
+ scan0 = (byte*)data.Scan0;
+ stride = data.Stride;
}
public void Dispose() {
@@ -104,26 +77,24 @@ namespace ClassicalSharp {
if( data != null ) {
Bitmap.UnlockBits( data );
data = null;
- accessor = null;
+ scan0 = (byte*)IntPtr.Zero;
+ stride = 0;
}
}
- /// Gets the colour of the pixel at the specified coordinates.
- /// X coordinate of the pixel.
- /// Y coordinate of the pixel.
- /// Does *not* perform bounds checking for performance reasons.
- /// The colour at that pixel, in ARGB form. (A is highest 24 bits)
public int GetPixel( int x, int y ) {
- return accessor.GetPixel( x, y );
+ // TODO: Does this work with big-endian systems?
+ int* row = (int*)( scan0 + ( y * stride ) );
+ return row[x]; // b g r a
+ }
+
+ public int* GetRowPtr( int y ) {
+ return (int*)( scan0 + ( y * stride ) );
}
- /// Sets the colour of the pixel at the specified coordinates.
- /// X coordinate of the pixel.
- /// Y coordinate of the pixel.
- /// The new colour of the pixel, in ARGB form. (A is highest 8 bits)
- /// Does *not* perform bounds checking for performance reasons.
public void SetPixel( int x, int y, int col ) {
- accessor.SetPixel( x, y, col );
+ int* row = (int*)( scan0 + ( y * stride ) );
+ row[x] = col;
}
}
}
\ No newline at end of file
diff --git a/TextureAtlas2D.cs b/TextureAtlas2D.cs
index f03aa83b0..be9c64139 100644
--- a/TextureAtlas2D.cs
+++ b/TextureAtlas2D.cs
@@ -146,13 +146,14 @@ namespace ClassicalSharp {
y = id / ElementsPerRow;
}
- void CopyPortion( int x, int y, int destX, int destY, FastBitmap atlas, FastBitmap dest ) {
- int atlasX = x * horElementSize;
- int atlasY = y * verElementSize;
- for( int pixelY = 0; pixelY < verElementSize; pixelY++ ) {
- for( int pixelX = 0; pixelX < horElementSize; pixelX++ ) {
- int col = atlas.GetPixel( atlasX + pixelX, atlasY + pixelY );
- dest.SetPixel( destX + pixelX, destY + pixelY, col );
+ unsafe void CopyPortion( int tileX, int tileY, int dstX, int dstY, FastBitmap atlas, FastBitmap dst ) {
+ int atlasX = tileX * horElementSize;
+ int atlasY = tileY * verElementSize;
+ for( int y = 0; y < verElementSize; y++ ) {
+ int* srcRow = atlas.GetRowPtr( atlasY + y );
+ int* dstRow = dst.GetRowPtr( dstY + y );
+ for( int x = 0; x < horElementSize; x++ ) {
+ dstRow[dstX + x] = srcRow[atlasX + x];
}
}
}