Browse Source

Fix diffusion tests

af/merge-core
James Jackson-South 9 years ago
parent
commit
8893450a8a
  1. 10
      src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs
  2. 16
      src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
  3. 4
      src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
  4. 2
      src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs
  5. 38
      src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
  6. 38
      src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
  7. 2
      src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs
  8. 2
      src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs
  9. 2
      src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
  10. 3
      tests/ImageSharp.Tests/Processing/Processors/Binarization/DitherTests.cs

10
src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs

@ -69,15 +69,15 @@ namespace SixLabors.ImageSharp.Dithering
/// <inheritdoc /> /// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dither<TPixel>(ImageBase<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int width, int height) public void Dither<TPixel>(ImageBase<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
this.Dither(pixels, source, transformed, x, y, width, height, true); this.Dither(pixels, source, transformed, x, y, minX, minY, maxX, maxY, true);
} }
/// <inheritdoc /> /// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel) public void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY, bool replacePixel)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
if (replacePixel) if (replacePixel)
@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Dithering
for (int row = 0; row < this.matrixHeight; row++) for (int row = 0; row < this.matrixHeight; row++)
{ {
int matrixY = y + row; int matrixY = y + row;
if (matrixY > 0 && matrixY < height) if (matrixY > minY && matrixY < maxY)
{ {
Span<TPixel> rowSpan = image.GetRowSpan(matrixY); Span<TPixel> rowSpan = image.GetRowSpan(matrixY);
@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Dithering
{ {
int matrixX = x + (col - this.startingOffset); int matrixX = x + (col - this.startingOffset);
if (matrixX > 0 && matrixX < width) if (matrixX > minX && matrixX < maxX)
{ {
float coefficient = this.matrix[row, col]; float coefficient = this.matrix[row, col];

16
src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs

@ -18,10 +18,12 @@ namespace SixLabors.ImageSharp.Dithering
/// <param name="transformed">The transformed pixel</param> /// <param name="transformed">The transformed pixel</param>
/// <param name="x">The column index.</param> /// <param name="x">The column index.</param>
/// <param name="y">The row index.</param> /// <param name="y">The row index.</param>
/// <param name="width">The image width.</param> /// <param name="minX">The minimum column value.</param>
/// <param name="height">The image height.</param> /// <param name="minY">The minimum row value.</param>
/// <param name="maxX">The maximum column value.</param>
/// <param name="maxY">The maximum row value.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int width, int height) void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY)
where TPixel : struct, IPixel<TPixel>; where TPixel : struct, IPixel<TPixel>;
/// <summary> /// <summary>
@ -32,14 +34,16 @@ namespace SixLabors.ImageSharp.Dithering
/// <param name="transformed">The transformed pixel</param> /// <param name="transformed">The transformed pixel</param>
/// <param name="x">The column index.</param> /// <param name="x">The column index.</param>
/// <param name="y">The row index.</param> /// <param name="y">The row index.</param>
/// <param name="width">The image width.</param> /// <param name="minX">The minimum column value.</param>
/// <param name="height">The image height.</param> /// <param name="minY">The minimum row value.</param>
/// <param name="maxX">The maximum column value.</param>
/// <param name="maxY">The maximum row value.</param>
/// <param name="replacePixel"> /// <param name="replacePixel">
/// Whether to replace the pixel at the given coordinates with the transformed value. /// Whether to replace the pixel at the given coordinates with the transformed value.
/// Generally this would be true for standard two-color dithering but when used in conjunction with color quantization this should be false. /// Generally this would be true for standard two-color dithering but when used in conjunction with color quantization this should be false.
/// </param> /// </param>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel) void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY, bool replacePixel)
where TPixel : struct, IPixel<TPixel>; where TPixel : struct, IPixel<TPixel>;
} }
} }

4
src/ImageSharp/Dithering/Ordered/IOrderedDither.cs

@ -21,10 +21,8 @@ namespace SixLabors.ImageSharp.Dithering
/// <param name="index">The component index to test the threshold against. Must range from 0 to 3.</param> /// <param name="index">The component index to test the threshold against. Must range from 0 to 3.</param>
/// <param name="x">The column index.</param> /// <param name="x">The column index.</param>
/// <param name="y">The row index.</param> /// <param name="y">The row index.</param>
/// <param name="width">The image width.</param>
/// <param name="height">The image height.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height) void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y)
where TPixel : struct, IPixel<TPixel>; where TPixel : struct, IPixel<TPixel>;
} }
} }

2
src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Dithering.Ordered
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height) public void Dither<TPixel>(ImageBase<TPixel> image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
// TODO: This doesn't really cut it for me. // TODO: This doesn't really cut it for me.

38
src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs

@ -61,39 +61,21 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{ {
int startY = sourceRectangle.Y; var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
int endY = sourceRectangle.Bottom; int startY = interest.Y;
int startX = sourceRectangle.X; int endY = interest.Bottom;
int endX = sourceRectangle.Right; int startX = interest.X;
int endX = interest.Right;
// Align start/end positions. for (int y = startY; y < endY; y++)
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
for (int y = minY; y < maxY; y++)
{ {
int offsetY = y - startY; Span<TPixel> row = source.GetRowSpan(y);
Span<TPixel> row = source.GetRowSpan(offsetY);
for (int x = minX; x < maxX; x++) for (int x = startX; x < endX; x++)
{ {
int offsetX = x - startX; TPixel sourceColor = row[x];
TPixel sourceColor = row[offsetX];
TPixel transformedColor = sourceColor.ToVector4().X >= this.Threshold ? this.UpperColor : this.LowerColor; TPixel transformedColor = sourceColor.ToVector4().X >= this.Threshold ? this.UpperColor : this.LowerColor;
this.Diffuser.Dither(source, sourceColor, transformedColor, offsetX, offsetY, maxX, maxY); this.Diffuser.Dither(source, sourceColor, transformedColor, x, y, startX, startY, endX, endY);
} }
} }
} }

38
src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs

@ -69,39 +69,21 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{ {
int startY = sourceRectangle.Y; var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
int endY = sourceRectangle.Bottom; int startY = interest.Y;
int startX = sourceRectangle.X; int endY = interest.Bottom;
int endX = sourceRectangle.Right; int startX = interest.X;
int endX = interest.Right;
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
byte[] bytes = new byte[4]; byte[] bytes = new byte[4];
for (int y = minY; y < maxY; y++) for (int y = startY; y < endY; y++)
{ {
int offsetY = y - startY; Span<TPixel> row = source.GetRowSpan(y);
Span<TPixel> row = source.GetRowSpan(offsetY);
for (int x = minX; x < maxX; x++) for (int x = startX; x < endX; x++)
{ {
int offsetX = x - startX; TPixel sourceColor = row[x];
TPixel sourceColor = row[offsetX]; this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, x, y);
this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, offsetX, offsetY, maxX, maxY);
} }
} }
} }

2
src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs

@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Quantizers
if (this.Dither) if (this.Dither)
{ {
// Apply the dithering matrix. We have to reapply the value now as the original has changed. // Apply the dithering matrix. We have to reapply the value now as the original has changed.
this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, width, height, false); this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, 0, 0, width, height, false);
} }
output[(y * source.Width) + x] = pixelValue; output[(y * source.Width) + x] = pixelValue;

2
src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs

@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Quantizers
if (this.Dither) if (this.Dither)
{ {
// Apply the dithering matrix. We have to reapply the value now as the original has changed. // Apply the dithering matrix. We have to reapply the value now as the original has changed.
this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, width, height, false); this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, 0, 0, width, height, false);
} }
output[(y * source.Width) + x] = pixelValue; output[(y * source.Width) + x] = pixelValue;

2
src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs

@ -277,7 +277,7 @@ namespace SixLabors.ImageSharp.Quantizers
if (this.Dither) if (this.Dither)
{ {
// Apply the dithering matrix. We have to reapply the value now as the original has changed. // Apply the dithering matrix. We have to reapply the value now as the original has changed.
this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, width, height, false); this.DitherType.Dither(source, sourcePixel, transformedPixel, x, y, 0, 0, width, height, false);
} }
output[(y * source.Width) + x] = pixelValue; output[(y * source.Width) + x] = pixelValue;

3
tests/ImageSharp.Tests/Processing/Processors/Binarization/DitherTests.cs

@ -111,8 +111,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
} }
} }
// TODO: Does not work because of a bug! Fix it! [Theory]
[Theory(Skip = "TODO: Does not work because of a bug! Fix it!")]
[WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)]
public void ApplyDiffusionFilterInBox<TPixel>(TestImageProvider<TPixel> provider) public void ApplyDiffusionFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>

Loading…
Cancel
Save