diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 48106d7c4..0ffb91bf5 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -26,6 +26,7 @@
4
bin\Debug\ImageProcessor.XML
false
+ true
pdbonly
@@ -73,7 +74,9 @@
-
+
+ Code
+
diff --git a/src/ImageProcessor/Imaging/FastBitmap.cs b/src/ImageProcessor/Imaging/FastBitmap.cs
index 1ab929c10..97af88356 100644
--- a/src/ImageProcessor/Imaging/FastBitmap.cs
+++ b/src/ImageProcessor/Imaging/FastBitmap.cs
@@ -13,12 +13,11 @@ namespace ImageProcessor.Imaging
using System;
using System.Drawing;
using System.Drawing.Imaging;
- using System.Runtime.InteropServices;
///
/// Allows fast access to 's pixel data.
///
- public class FastBitmap : IDisposable
+ public unsafe class FastBitmap : IDisposable
{
///
/// The bitmap.
@@ -36,24 +35,24 @@ namespace ImageProcessor.Imaging
private readonly int height;
///
- /// The stride width of the bitmap.
+ /// The number of bytes in a row.
///
- private int stride;
+ private int bytesInARow;
///
- /// The bitmap data.
+ /// The size of the pixel data.
///
- private BitmapData bitmapData;
+ private int pixelDataSize;
///
- /// The pixel buffer for holding pixel data.
+ /// The bitmap data.
///
- private byte[] pixelBuffer;
+ private BitmapData bitmapData;
///
- /// The buffer length.
+ /// The pixel buffer for holding pixel data.
///
- private int bufferLength;
+ private byte* pixelBuffer;
///
/// A value indicating whether this instance of the given entity has been disposed.
@@ -102,6 +101,23 @@ namespace ImageProcessor.Imaging
}
}
+ ///
+ /// Gets the pixel data for the given position.
+ ///
+ ///
+ /// The x position of the pixel.
+ ///
+ ///
+ /// The y position of the pixel.
+ ///
+ ///
+ /// The .
+ ///
+ private PixelData* this[int x, int y]
+ {
+ get { return (PixelData*)(this.pixelBuffer + (y * this.bytesInARow) + (x * this.pixelDataSize)); }
+ }
+
///
/// Allows the implicit conversion of an instance of to a
/// .
@@ -150,12 +166,8 @@ namespace ImageProcessor.Imaging
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
}
- int position = (x * 4) + (y * this.stride);
- byte blue = this.pixelBuffer[position];
- byte green = this.pixelBuffer[position + 1];
- byte red = this.pixelBuffer[position + 2];
- byte alpha = this.pixelBuffer[position + 3];
- return Color.FromArgb(alpha, red, green, blue);
+ PixelData* data = this[x, y];
+ return Color.FromArgb(data->A, data->R, data->G, data->B);
}
///
@@ -179,11 +191,11 @@ namespace ImageProcessor.Imaging
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
}
- int position = (x * 4) + (y * this.stride);
- this.pixelBuffer[position] = color.B;
- this.pixelBuffer[position + 1] = color.G;
- this.pixelBuffer[position + 2] = color.R;
- this.pixelBuffer[position + 3] = color.A;
+ PixelData* data = this[x, y];
+ data->R = color.R;
+ data->G = color.G;
+ data->B = color.B;
+ data->A = color.A;
}
///
@@ -231,14 +243,21 @@ namespace ImageProcessor.Imaging
{
Rectangle bounds = new Rectangle(Point.Empty, this.bitmap.Size);
+ // Figure out the number of bytes in a row. This is rounded up to be a multiple
+ // of 4 bytes, since a scan line in an image must always be a multiple of 4 bytes
+ // in length.
+ this.pixelDataSize = sizeof(PixelData);
+ this.bytesInARow = bounds.Width * this.pixelDataSize;
+ if (this.bytesInARow % 4 != 0)
+ {
+ this.bytesInARow = 4 * ((this.bytesInARow / 4) + 1);
+ }
+
// Lock the bitmap
this.bitmapData = this.bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// Copy the bitmap data across to the array for manipulation.
- this.stride = this.bitmapData.Stride;
- this.bufferLength = this.stride * this.bitmapData.Height;
- this.pixelBuffer = new byte[this.bufferLength];
- Marshal.Copy(this.bitmapData.Scan0, this.pixelBuffer, 0, this.pixelBuffer.Length);
+ this.pixelBuffer = (byte*)this.bitmapData.Scan0.ToPointer();
}
///
@@ -247,10 +266,35 @@ namespace ImageProcessor.Imaging
private void UnlockBitmap()
{
// Copy the RGB values back to the bitmap and unlock the bitmap.
- Marshal.Copy(this.pixelBuffer, 0, this.bitmapData.Scan0, this.bufferLength);
this.bitmap.UnlockBits(this.bitmapData);
this.bitmapData = null;
this.pixelBuffer = null;
}
+
+ ///
+ /// The pixel data.
+ ///
+ private struct PixelData
+ {
+ ///
+ /// The blue component.
+ ///
+ public byte B;
+
+ ///
+ /// The green component.
+ ///
+ public byte G;
+
+ ///
+ /// The red component.
+ ///
+ public byte R;
+
+ ///
+ /// The alpha component.
+ ///
+ public byte A;
+ }
}
}
diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs
index 4b7651445..73bc58733 100644
--- a/src/ImageProcessorConsole/Program.cs
+++ b/src/ImageProcessorConsole/Program.cs
@@ -74,9 +74,10 @@ namespace ImageProcessorConsole
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
.Constrain(size)
+ .Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)
- .GaussianSharpen(10)
+ //.GaussianSharpen(10)
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));
stopwatch.Stop();