Browse Source

F**ck me it works!

Former-commit-id: 5349fc67232b2863c8e5d6fa880ffd1bd415efa3
Former-commit-id: 5e92562e0c7131b65d41ff81ba48bbc0f83b60d8
Former-commit-id: 79570635457be4888019984092c73105a159848d
pull/1/head
James Jackson-South 10 years ago
parent
commit
4608c5c87d
  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>
/// <param name="image">The image</param>
/// <returns>The <see cref="IPixelAccessor"/></returns>
public IPixelAccessor<TPackedVector> GetPixelAccessor<TPackedVector>(IImageBase image)
public IPixelAccessor GetPixelAccessor<TPackedVector>(IImageBase image)
where TPackedVector : IPackedVector, new()
{
Type packed = typeof(TPackedVector);
@ -82,33 +82,7 @@ namespace ImageProcessorCore
{
// TODO: Double check this. It should work...
return (IPixelAccessor<TPackedVector>)new Bgra32PixelAccessor<TPackedVector>(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 new Bgra32PixelAccessor(image);
return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image);
}
@ -122,5 +96,31 @@ namespace ImageProcessorCore
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/>
public void Encode<TPackedVector>(ImageBase<TPackedVector> image, Stream stream)
where TPackedVector: IPackedVector
where TPackedVector : IPackedVector, new()
{
BmpEncoderCore encoder = new BmpEncoderCore();
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="bitsPerPixel">The <see cref="BmpBitsPerPixel"/></param>
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(stream, nameof(stream));
@ -128,7 +128,7 @@ namespace ImageProcessorCore.Formats
/// The <see cref="ImageBase{TPackedVector}"/> containing pixel data.
/// </param>
private void WriteImage<TPackedVector>(EndianBinaryWriter writer, ImageBase<TPackedVector> image)
where TPackedVector : IPackedVector
where TPackedVector : IPackedVector, new()
{
// TODO: Add more compression formats.
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>
/// <param name="image">The <see cref="ImageBase{TPackedVector}"/> to decode to.</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>
/// <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>
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()
{
TPackedVector[] Pixels { get; }
void ClonePixels(int width, int height, IEnumerable<TPackedVector> pixels);
IPixelAccessor<TPackedVector> Lock();
void ClonePixels(int width, int height, TPackedVector[] pixels);
IPixelAccessor Lock();
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; }
/// <inheritdoc/>
public override IPixelAccessor<TPackedVector> Lock()
public override IPixelAccessor Lock()
{
return Bootstrapper.Instance.GetPixelAccessor(this);
return Bootstrapper.Instance.GetPixelAccessor<TPackedVector>(this);
}
/// <summary>

2
src/ImageProcessorCore/ImageBase.cs

@ -196,6 +196,6 @@ namespace ImageProcessorCore
/// </remarks>
/// </summary>
/// <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 />
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
/// alpha values are 8 bit unsigned bytes.
/// </remarks>
public sealed unsafe class Bgra32PixelAccessor<TPackedVector> : IPixelAccessor<Bgra32>
public sealed unsafe class Bgra32PixelAccessor : IPixelAccessor
{
/// <summary>
@ -90,7 +90,7 @@ namespace ImageProcessorCore
/// than zero and smaller than the width of the pixel.
/// </param>
/// <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
{
@ -121,7 +121,7 @@ namespace ImageProcessorCore
throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height.");
}
#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>
/// Encapsulates properties to provides per-pixel access to an images pixels.
/// </summary>
public interface IPixelAccessor<TPackedVector> : IDisposable where TPackedVector : IPackedVector, new()
public interface IPixelAccessor : IDisposable
{
/// <summary>
/// Gets the width of the image in pixels.
@ -34,7 +34,7 @@ namespace ImageProcessorCore
/// than zero and smaller than the width of the pixel.
/// </param>
/// <returns>The <see cref="TPackedVector"/> at the specified position.</returns>
TPackedVector this[int x, int y]
IPackedVector this[int x, int y]
{
get;
set;

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

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

Loading…
Cancel
Save