Browse Source

F**ck me it works!

Former-commit-id: 5349fc67232b2863c8e5d6fa880ffd1bd415efa3
Former-commit-id: 5e92562e0c7131b65d41ff81ba48bbc0f83b60d8
Former-commit-id: 79570635457be4888019984092c73105a159848d
af/merge-core
James Jackson-South 10 years ago
parent
commit
a1383fdaf3
  1. 56
      src/ImageProcessorCore/Bootstrapper.cs
  2. 2
      src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs
  3. 4
      src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
  4. 3
      src/ImageProcessorCore/Formats/IImageDecoder.cs
  5. 3
      src/ImageProcessorCore/Formats/IImageEncoder.cs
  6. 4
      src/ImageProcessorCore/IImageBase.cs
  7. 4
      src/ImageProcessorCore/Image.cs
  8. 2
      src/ImageProcessorCore/ImageBase.cs
  9. 4
      src/ImageProcessorCore/ImageFrame.cs
  10. 6
      src/ImageProcessorCore/PixelAccessor/Bgra32PixelAccessor.cs
  11. 4
      src/ImageProcessorCore/PixelAccessor/IPixelAccessor.cs
  12. 156
      src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs

56
src/ImageProcessorCore/Bootstrapper.cs

@ -74,7 +74,7 @@ namespace ImageProcessorCore
/// <typeparam name="TPackedVector">The type of pixel data.</typeparam> /// <typeparam name="TPackedVector">The type of pixel data.</typeparam>
/// <param name="image">The image</param> /// <param name="image">The image</param>
/// <returns>The <see cref="IPixelAccessor"/></returns> /// <returns>The <see cref="IPixelAccessor"/></returns>
public IPixelAccessor<TPackedVector> GetPixelAccessor<TPackedVector>(IImageBase image) public IPixelAccessor GetPixelAccessor<TPackedVector>(IImageBase image)
where TPackedVector : IPackedVector, new() where TPackedVector : IPackedVector, new()
{ {
Type packed = typeof(TPackedVector); Type packed = typeof(TPackedVector);
@ -82,33 +82,7 @@ namespace ImageProcessorCore
{ {
// TODO: Double check this. It should work... // TODO: Double check this. It should work...
return (IPixelAccessor<TPackedVector>)new Bgra32PixelAccessor<TPackedVector>(image); //return new Bgra32PixelAccessor(image);
//return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image);
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("PixelAccessor cannot be loaded. Available accessors:");
foreach (Type value in this.pixelAccessors.Values)
{
stringBuilder.AppendLine("-" + value.Name);
}
throw new NotSupportedException(stringBuilder.ToString());
}
/// <summary>
/// Gets an instance of the correct <see cref="IPixelAccessor"/> for the packed vector.
/// </summary>
/// <typeparam name="TPackedVector">The type of pixel data.</typeparam>
/// <param name="image">The image</param>
/// <returns>The <see cref="IPixelAccessor"/></returns>
public IPixelAccessor GetPixelAccessor<TPackedVector>(ImageFrame<TPackedVector> image)
where TPackedVector : IPackedVector
{
Type packed = typeof(TPackedVector);
if (!this.pixelAccessors.ContainsKey(packed))
{
return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image); return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image);
} }
@ -122,5 +96,31 @@ namespace ImageProcessorCore
throw new NotSupportedException(stringBuilder.ToString()); throw new NotSupportedException(stringBuilder.ToString());
} }
///// <summary>
///// Gets an instance of the correct <see cref="IPixelAccessor"/> for the packed vector.
///// </summary>
///// <typeparam name="TPackedVector">The type of pixel data.</typeparam>
///// <param name="image">The image</param>
///// <returns>The <see cref="IPixelAccessor"/></returns>
//public IPixelAccessor GetPixelAccessor<TPackedVector>(ImageFrame<TPackedVector> image)
// where TPackedVector : IPackedVector, new()
//{
// Type packed = typeof(TPackedVector);
// if (!this.pixelAccessors.ContainsKey(packed))
// {
// return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image);
// }
// StringBuilder stringBuilder = new StringBuilder();
// stringBuilder.AppendLine("PixelAccessor cannot be loaded. Available accessors:");
// foreach (Type value in this.pixelAccessors.Values)
// {
// stringBuilder.AppendLine("-" + value.Name);
// }
// throw new NotSupportedException(stringBuilder.ToString());
//}
} }
} }

2
src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs

@ -44,7 +44,7 @@ namespace ImageProcessorCore.Formats
/// <inheritdoc/> /// <inheritdoc/>
public void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream) public void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream)
where TPackedVector: IPackedVector where TPackedVector : IPackedVector, new()
{ {
BmpEncoderCore encoder = new BmpEncoderCore(); BmpEncoderCore encoder = new BmpEncoderCore();
encoder.Encode(image, stream, this.BitsPerPixel); encoder.Encode(image, stream, this.BitsPerPixel);

4
src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs

@ -29,7 +29,7 @@ namespace ImageProcessorCore.Formats
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param> /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="bitsPerPixel">The <see cref="BmpBitsPerPixel"/></param> /// <param name="bitsPerPixel">The <see cref="BmpBitsPerPixel"/></param>
public void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream, BmpBitsPerPixel bitsPerPixel) public void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream, BmpBitsPerPixel bitsPerPixel)
where TPackedVector : IPackedVector where TPackedVector : IPackedVector, new()
{ {
Guard.NotNull(image, nameof(image)); Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
@ -128,7 +128,7 @@ namespace ImageProcessorCore.Formats
/// The <see cref="ImageBase{TPackedVector}"/> containing pixel data. /// The <see cref="ImageBase{TPackedVector}"/> containing pixel data.
/// </param> /// </param>
private void WriteImage<TPackedVector>(EndianBinaryWriter writer, ImageBase<TPackedVector> image) private void WriteImage<TPackedVector>(EndianBinaryWriter writer, ImageBase<TPackedVector> image)
where TPackedVector : IPackedVector where TPackedVector : IPackedVector, new()
{ {
// TODO: Add more compression formats. // TODO: Add more compression formats.
int amount = (image.Width * (int)this.bmpBitsPerPixel) % 4; int amount = (image.Width * (int)this.bmpBitsPerPixel) % 4;

3
src/ImageProcessorCore/Formats/IImageDecoder.cs

@ -44,6 +44,7 @@ namespace ImageProcessorCore.Formats
/// <typeparam name="TPackedVector">The type of pixels contained within the image.</typeparam> /// <typeparam name="TPackedVector">The type of pixels contained within the image.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPackedVector}"/> to decode to.</param> /// <param name="image">The <see cref="ImageBase{TPackedVector}"/> to decode to.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param> /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
void Decode<TPackedVector>(Image<TPackedVector> image, Stream stream) where TPackedVector : IPackedVector, new(); void Decode<TPackedVector>(Image<TPackedVector> image, Stream stream)
where TPackedVector : IPackedVector, new();
} }
} }

3
src/ImageProcessorCore/Formats/IImageEncoder.cs

@ -48,6 +48,7 @@ namespace ImageProcessorCore.Formats
/// <typeparam name="TPackedVector">The type of pixels contained within the image.</typeparam> /// <typeparam name="TPackedVector">The type of pixels contained within the image.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPackedVector}"/> to encode from.</param> /// <param name="image">The <see cref="ImageBase{TPackedVector}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param> /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream) where TPackedVector : IPackedVector; void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream)
where TPackedVector : IPackedVector, new();
} }
} }

4
src/ImageProcessorCore/IImageBase.cs

@ -6,8 +6,8 @@ namespace ImageProcessorCore
where TPackedVector : IPackedVector, new() where TPackedVector : IPackedVector, new()
{ {
TPackedVector[] Pixels { get; } TPackedVector[] Pixels { get; }
void ClonePixels(int width, int height, IEnumerable<TPackedVector> pixels); void ClonePixels(int width, int height, TPackedVector[] pixels);
IPixelAccessor<TPackedVector> Lock(); IPixelAccessor Lock();
void SetPixels(int width, int height, TPackedVector[] pixels); void SetPixels(int width, int height, TPackedVector[] pixels);
} }

4
src/ImageProcessorCore/Image.cs

@ -184,9 +184,9 @@ namespace ImageProcessorCore
public IImageFormat CurrentImageFormat { get; internal set; } public IImageFormat CurrentImageFormat { get; internal set; }
/// <inheritdoc/> /// <inheritdoc/>
public override IPixelAccessor<TPackedVector> Lock() public override IPixelAccessor Lock()
{ {
return Bootstrapper.Instance.GetPixelAccessor(this); return Bootstrapper.Instance.GetPixelAccessor<TPackedVector>(this);
} }
/// <summary> /// <summary>

2
src/ImageProcessorCore/ImageBase.cs

@ -196,6 +196,6 @@ namespace ImageProcessorCore
/// </remarks> /// </remarks>
/// </summary> /// </summary>
/// <returns>The <see cref="IPixelAccessor"/></returns> /// <returns>The <see cref="IPixelAccessor"/></returns>
public abstract IPixelAccessor<TPackedVector> Lock(); public abstract IPixelAccessor Lock();
} }
} }

4
src/ImageProcessorCore/ImageFrame.cs

@ -33,9 +33,9 @@ namespace ImageProcessorCore
} }
/// <inheritdoc /> /// <inheritdoc />
public override IPixelAccessor<TPackedVector> Lock() public override IPixelAccessor Lock()
{ {
return Bootstrapper.Instance.GetPixelAccessor(this); return Bootstrapper.Instance.GetPixelAccessor<TPackedVector>(this);
} }
} }
} }

6
src/ImageProcessorCore/PixelAccessor/Bgra32PixelAccessor.cs

@ -15,7 +15,7 @@ namespace ImageProcessorCore
/// The image data is always stored in <see cref="Bgra32"/> format, where the blue, green, red, and /// The image data is always stored in <see cref="Bgra32"/> format, where the blue, green, red, and
/// alpha values are 8 bit unsigned bytes. /// alpha values are 8 bit unsigned bytes.
/// </remarks> /// </remarks>
public sealed unsafe class Bgra32PixelAccessor<TPackedVector> : IPixelAccessor<Bgra32> public sealed unsafe class Bgra32PixelAccessor : IPixelAccessor
{ {
/// <summary> /// <summary>
@ -90,7 +90,7 @@ namespace ImageProcessorCore
/// than zero and smaller than the width of the pixel. /// than zero and smaller than the width of the pixel.
/// </param> /// </param>
/// <returns>The <see cref="IPackedVector"/> at the specified position.</returns> /// <returns>The <see cref="IPackedVector"/> at the specified position.</returns>
public Bgra32 this[int x, int y] public IPackedVector this[int x, int y]
{ {
get get
{ {
@ -121,7 +121,7 @@ namespace ImageProcessorCore
throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height."); throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height.");
} }
#endif #endif
*(this.pixelsBase + ((y * this.Width) + x)) = value; *(this.pixelsBase + ((y * this.Width) + x)) = (Bgra32)value;
} }
} }

4
src/ImageProcessorCore/PixelAccessor/IPixelAccessor.cs

@ -10,7 +10,7 @@ namespace ImageProcessorCore
/// <summary> /// <summary>
/// Encapsulates properties to provides per-pixel access to an images pixels. /// Encapsulates properties to provides per-pixel access to an images pixels.
/// </summary> /// </summary>
public interface IPixelAccessor<TPackedVector> : IDisposable where TPackedVector : IPackedVector, new() public interface IPixelAccessor : IDisposable
{ {
/// <summary> /// <summary>
/// Gets the width of the image in pixels. /// Gets the width of the image in pixels.
@ -34,7 +34,7 @@ namespace ImageProcessorCore
/// than zero and smaller than the width of the pixel. /// than zero and smaller than the width of the pixel.
/// </param> /// </param>
/// <returns>The <see cref="TPackedVector"/> at the specified position.</returns> /// <returns>The <see cref="TPackedVector"/> at the specified position.</returns>
TPackedVector this[int x, int y] IPackedVector this[int x, int y]
{ {
get; get;
set; set;

156
src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs

@ -14,11 +14,6 @@ namespace ImageProcessorCore.Processors
/// </summary> /// </summary>
public class ResizeProcessor : ImageSampler public class ResizeProcessor : ImageSampler
{ {
/// <summary>
/// The image used for storing the first pass pixels.
/// </summary>
private object firstPass;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class. /// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
/// </summary> /// </summary>
@ -55,8 +50,6 @@ namespace ImageProcessorCore.Processors
this.HorizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width); this.HorizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width);
this.VerticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height); this.VerticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height);
} }
this.firstPass = new Image<TPackedVector>(target.Width, source.Height);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -79,17 +72,14 @@ namespace ImageProcessorCore.Processors
int endX = targetRectangle.Right; int endX = targetRectangle.Right;
bool compand = this.Compand; bool compand = this.Compand;
// TODO: Yuck! Fix this boxing nonsense
Image<TPackedVector> fp = (Image<TPackedVector>)this.firstPass;
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
// Scaling factors // Scaling factors
float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width; float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height; float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height;
using (IPixelAccessor<TPackedVector> sourcePixels = source.Lock()) using (IPixelAccessor sourcePixels = source.Lock())
using (IPixelAccessor<TPackedVector> targetPixels = target.Lock()) using (IPixelAccessor targetPixels = target.Lock())
{ {
Parallel.For( Parallel.For(
startY, startY,
@ -124,94 +114,114 @@ namespace ImageProcessorCore.Processors
// A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
// First process the columns. Since we are not using multiple threads startY and endY // First process the columns. Since we are not using multiple threads startY and endY
// are the upper and lower bounds of the source rectangle. // are the upper and lower bounds of the source rectangle.
using (IPixelAccessor<TPackedVector> sourcePixels = source.Lock()) Image<TPackedVector> firstPass = new Image<TPackedVector>(target.Width, source.Height);
using (IPixelAccessor<TPackedVector> firstPassPixels = fp.Lock()) using (IPixelAccessor sourcePixels = source.Lock())
using (IPixelAccessor<TPackedVector> targetPixels = target.Lock()) using (IPixelAccessor firstPassPixels = firstPass.Lock())
using (IPixelAccessor targetPixels = target.Lock())
{ {
Parallel.For( Parallel.For(
0, 0,
sourceHeight, sourceHeight,
y => y =>
{
for (int x = startX; x < endX; x++)
{ {
for (int x = startX; x < endX; x++) if (x >= 0 && x < width)
{ {
if (x >= 0 && x < width) // Ensure offsets are normalised for cropping and padding.
{ int offsetX = x - startX;
// Ensure offsets are normalised for cropping and padding. float sum = this.HorizontalWeights[offsetX].Sum;
int offsetX = x - startX; Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values;
float sum = this.HorizontalWeights[offsetX].Sum;
Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values;
// Destination color components // Destination color components
Vector4 destination = new Vector4(); //Color destination = new Color();
for (int i = 0; i < sum; i++) //for (int i = 0; i < sum; i++)
{ //{
Weight xw = horizontalValues[i]; // Weight xw = horizontalValues[i];
int originX = xw.Index; // int originX = xw.Index;
Vector4 sourceColor = sourcePixels[originX, y].ToVector4(); // Color sourceColor = compand
//Color sourceColor = compand // ? Color.Expand(sourcePixels[originX, y])
// ? Color.Expand(sourcePixels[originX, y]) // : sourcePixels[originX, y];
// : sourcePixels[originX, y];
// destination += sourceColor * xw.Value;
destination += sourceColor * xw.Value; //}
}
//if (compand) //if (compand)
//{ //{
// destination = Color.Compress(destination); // destination = Color.Compress(destination);
//} //}
TPackedVector packed = new TPackedVector();
packed.PackVector(destination); //firstPassPixels[x, y] = destination;
firstPassPixels[x, y] = packed; Vector4 destination = new Vector4();
for (int i = 0; i < sum; i++)
{
Weight xw = horizontalValues[i];
int originX = xw.Index;
Vector4 sourceColor = sourcePixels[originX, y].ToVector4();
//Color sourceColor = compand
// ? Color.Expand(sourcePixels[originX, y])
// : sourcePixels[originX, y];
destination += sourceColor * xw.Value;
} }
//if (compand)
//{
// destination = Color.Compress(destination);
//}
TPackedVector packed = new TPackedVector();
packed.PackVector(destination);
firstPassPixels[x, y] = packed;
} }
}); }
});
// Now process the rows. // Now process the rows.
Parallel.For( Parallel.For(
startY, startY,
endY, endY,
y => y =>
{
if (y >= 0 && y < height)
{ {
if (y >= 0 && y < height) // Ensure offsets are normalised for cropping and padding.
int offsetY = y - startY;
float sum = this.VerticalWeights[offsetY].Sum;
Weight[] verticalValues = this.VerticalWeights[offsetY].Values;
for (int x = 0; x < width; x++)
{ {
// Ensure offsets are normalised for cropping and padding. // Destination color components
int offsetY = y - startY; Vector4 destination = new Vector4();
float sum = this.VerticalWeights[offsetY].Sum;
Weight[] verticalValues = this.VerticalWeights[offsetY].Values;
for (int x = 0; x < width; x++) for (int i = 0; i < sum; i++)
{ {
// Destination color components Weight yw = verticalValues[i];
Vector4 destination = new Vector4(); int originY = yw.Index;
//Color sourceColor = compand
for (int i = 0; i < sum; i++) // ? Color.Expand(firstPassPixels[x, originY])
{ // : firstPassPixels[x, originY];
Weight yw = verticalValues[i]; Vector4 sourceColor = firstPassPixels[x, originY].ToVector4();
int originY = yw.Index; destination += sourceColor * yw.Value;
}
Vector4 sourceColor = sourcePixels[x, originY].ToVector4();
//Color sourceColor = compand
// ? Color.Expand(firstPassPixels[x, originY])
// : firstPassPixels[x, originY];
destination += sourceColor * yw.Value; //if (compand)
} //{
// destination = Color.Compress(destination);
//}
//if (compand) TPackedVector packed = new TPackedVector();
//{ packed.PackVector(destination);
// destination = Color.Compress(destination);
//}
TPackedVector packed = new TPackedVector(); targetPixels[x, y] = packed;
packed.PackVector(destination);
targetPixels[x, y] = packed;
}
} }
}
this.OnRowProcessed(); this.OnRowProcessed();
}); });
} }
} }

Loading…
Cancel
Save