Browse Source

Switching up fastbitmap class

Former-commit-id: 93c59d9d01fe0bcc0751c959ed2f28be4192a500
af/merge-core
James South 12 years ago
parent
commit
36b33a7593
  1. 5
      src/ImageProcessor/ImageProcessor.csproj
  2. 96
      src/ImageProcessor/Imaging/FastBitmap.cs
  3. 3
      src/ImageProcessorConsole/Program.cs

5
src/ImageProcessor/ImageProcessor.csproj

@ -26,6 +26,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\ImageProcessor.XML</DocumentationFile> <DocumentationFile>bin\Debug\ImageProcessor.XML</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -73,7 +74,9 @@
<Compile Include="Imaging\Colors\HslaColor.cs" /> <Compile Include="Imaging\Colors\HslaColor.cs" />
<Compile Include="Imaging\Colors\RgbaColor.cs" /> <Compile Include="Imaging\Colors\RgbaColor.cs" />
<Compile Include="Imaging\Colors\YCbCrColor.cs" /> <Compile Include="Imaging\Colors\YCbCrColor.cs" />
<Compile Include="Imaging\FastBitmap.cs" /> <Compile Include="Imaging\FastBitmap.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Imaging\Formats\GifInfo.cs" /> <Compile Include="Imaging\Formats\GifInfo.cs" />
<Compile Include="Common\Extensions\IntegerExtensions.cs" /> <Compile Include="Common\Extensions\IntegerExtensions.cs" />
<Compile Include="Common\Exceptions\ImageFormatException.cs" /> <Compile Include="Common\Exceptions\ImageFormatException.cs" />

96
src/ImageProcessor/Imaging/FastBitmap.cs

@ -13,12 +13,11 @@ namespace ImageProcessor.Imaging
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices;
/// <summary> /// <summary>
/// Allows fast access to <see cref="System.Drawing.Bitmap"/>'s pixel data. /// Allows fast access to <see cref="System.Drawing.Bitmap"/>'s pixel data.
/// </summary> /// </summary>
public class FastBitmap : IDisposable public unsafe class FastBitmap : IDisposable
{ {
/// <summary> /// <summary>
/// The bitmap. /// The bitmap.
@ -36,24 +35,24 @@ namespace ImageProcessor.Imaging
private readonly int height; private readonly int height;
/// <summary> /// <summary>
/// The stride width of the bitmap. /// The number of bytes in a row.
/// </summary> /// </summary>
private int stride; private int bytesInARow;
/// <summary> /// <summary>
/// The bitmap data. /// The size of the pixel data.
/// </summary> /// </summary>
private BitmapData bitmapData; private int pixelDataSize;
/// <summary> /// <summary>
/// The pixel buffer for holding pixel data. /// The bitmap data.
/// </summary> /// </summary>
private byte[] pixelBuffer; private BitmapData bitmapData;
/// <summary> /// <summary>
/// The buffer length. /// The pixel buffer for holding pixel data.
/// </summary> /// </summary>
private int bufferLength; private byte* pixelBuffer;
/// <summary> /// <summary>
/// A value indicating whether this instance of the given entity has been disposed. /// A value indicating whether this instance of the given entity has been disposed.
@ -102,6 +101,23 @@ namespace ImageProcessor.Imaging
} }
} }
/// <summary>
/// Gets the pixel data for the given position.
/// </summary>
/// <param name="x">
/// The x position of the pixel.
/// </param>
/// <param name="y">
/// The y position of the pixel.
/// </param>
/// <returns>
/// The <see cref="PixelData"/>.
/// </returns>
private PixelData* this[int x, int y]
{
get { return (PixelData*)(this.pixelBuffer + (y * this.bytesInARow) + (x * this.pixelDataSize)); }
}
/// <summary> /// <summary>
/// Allows the implicit conversion of an instance of <see cref="FastBitmap"/> to a /// Allows the implicit conversion of an instance of <see cref="FastBitmap"/> to a
/// <see cref="System.Drawing.Image"/>. /// <see cref="System.Drawing.Image"/>.
@ -150,12 +166,8 @@ namespace ImageProcessor.Imaging
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height."); throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
} }
int position = (x * 4) + (y * this.stride); PixelData* data = this[x, y];
byte blue = this.pixelBuffer[position]; return Color.FromArgb(data->A, data->R, data->G, data->B);
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);
} }
/// <summary> /// <summary>
@ -179,11 +191,11 @@ namespace ImageProcessor.Imaging
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height."); throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
} }
int position = (x * 4) + (y * this.stride); PixelData* data = this[x, y];
this.pixelBuffer[position] = color.B; data->R = color.R;
this.pixelBuffer[position + 1] = color.G; data->G = color.G;
this.pixelBuffer[position + 2] = color.R; data->B = color.B;
this.pixelBuffer[position + 3] = color.A; data->A = color.A;
} }
/// <summary> /// <summary>
@ -231,14 +243,21 @@ namespace ImageProcessor.Imaging
{ {
Rectangle bounds = new Rectangle(Point.Empty, this.bitmap.Size); 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 // Lock the bitmap
this.bitmapData = this.bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); this.bitmapData = this.bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// Copy the bitmap data across to the array for manipulation. // Copy the bitmap data across to the array for manipulation.
this.stride = this.bitmapData.Stride; this.pixelBuffer = (byte*)this.bitmapData.Scan0.ToPointer();
this.bufferLength = this.stride * this.bitmapData.Height;
this.pixelBuffer = new byte[this.bufferLength];
Marshal.Copy(this.bitmapData.Scan0, this.pixelBuffer, 0, this.pixelBuffer.Length);
} }
/// <summary> /// <summary>
@ -247,10 +266,35 @@ namespace ImageProcessor.Imaging
private void UnlockBitmap() private void UnlockBitmap()
{ {
// Copy the RGB values back to the bitmap and unlock the bitmap. // 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.bitmap.UnlockBits(this.bitmapData);
this.bitmapData = null; this.bitmapData = null;
this.pixelBuffer = null; this.pixelBuffer = null;
} }
/// <summary>
/// The pixel data.
/// </summary>
private struct PixelData
{
/// <summary>
/// The blue component.
/// </summary>
public byte B;
/// <summary>
/// The green component.
/// </summary>
public byte G;
/// <summary>
/// The red component.
/// </summary>
public byte R;
/// <summary>
/// The alpha component.
/// </summary>
public byte A;
}
} }
} }

3
src/ImageProcessorConsole/Program.cs

@ -74,9 +74,10 @@ namespace ImageProcessorConsole
//.Resize(new Size((int)(size.Width * 1.1), 0)) //.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer) //.ContentAwareResize(layer)
.Constrain(size) .Constrain(size)
.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.HiSatch) //.Filter(MatrixFilters.HiSatch)
//.Pixelate(8) //.Pixelate(8)
.GaussianSharpen(10) //.GaussianSharpen(10)
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name))); .Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));
stopwatch.Stop(); stopwatch.Stop();

Loading…
Cancel
Save