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>
<DocumentationFile>bin\Debug\ImageProcessor.XML</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -73,7 +74,9 @@
<Compile Include="Imaging\Colors\HslaColor.cs" />
<Compile Include="Imaging\Colors\RgbaColor.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="Common\Extensions\IntegerExtensions.cs" />
<Compile Include="Common\Exceptions\ImageFormatException.cs" />

96
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;
/// <summary>
/// Allows fast access to <see cref="System.Drawing.Bitmap"/>'s pixel data.
/// </summary>
public class FastBitmap : IDisposable
public unsafe class FastBitmap : IDisposable
{
/// <summary>
/// The bitmap.
@ -36,24 +35,24 @@ namespace ImageProcessor.Imaging
private readonly int height;
/// <summary>
/// The stride width of the bitmap.
/// The number of bytes in a row.
/// </summary>
private int stride;
private int bytesInARow;
/// <summary>
/// The bitmap data.
/// The size of the pixel data.
/// </summary>
private BitmapData bitmapData;
private int pixelDataSize;
/// <summary>
/// The pixel buffer for holding pixel data.
/// The bitmap data.
/// </summary>
private byte[] pixelBuffer;
private BitmapData bitmapData;
/// <summary>
/// The buffer length.
/// The pixel buffer for holding pixel data.
/// </summary>
private int bufferLength;
private byte* pixelBuffer;
/// <summary>
/// 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>
/// Allows the implicit conversion of an instance of <see cref="FastBitmap"/> to a
/// <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.");
}
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);
}
/// <summary>
@ -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;
}
/// <summary>
@ -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();
}
/// <summary>
@ -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;
}
/// <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))
//.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();

Loading…
Cancel
Save