Browse Source

Make all images implement IDisposable

pull/97/head
James Jackson-South 9 years ago
parent
commit
d5064cadc5
  1. 4
      src/ImageSharp.Processing/Processors/Convolution/Convolution2DProcessor.cs
  2. 21
      src/ImageSharp.Processing/Processors/Convolution/Convolution2PassProcessor.cs
  3. 4
      src/ImageSharp.Processing/Processors/Effects/OilPaintingProcessor.cs
  4. 4
      src/ImageSharp.Processing/Processors/Effects/PixelateProcessor.cs
  5. 159
      src/ImageSharp.Processing/Processors/Transforms/CompandingResizeProcessor.cs
  6. 4
      src/ImageSharp.Processing/Processors/Transforms/CropProcessor.cs
  7. 8
      src/ImageSharp.Processing/Processors/Transforms/FlipProcessor.cs
  8. 159
      src/ImageSharp.Processing/Processors/Transforms/ResizeProcessor.cs
  9. 16
      src/ImageSharp.Processing/Processors/Transforms/RotateProcessor.cs
  10. 4
      src/ImageSharp.Processing/Processors/Transforms/SkewProcessor.cs
  11. 4
      src/ImageSharp/Image/IImageBase{TColor}.cs
  12. 111
      src/ImageSharp/Image/ImageBase{TColor}.cs
  13. 16
      src/ImageSharp/Image/Image{TColor}.cs
  14. 4
      src/ImageSharp/Image/PixelAccessor{TColor}.cs
  15. 50
      src/ImageSharp/Image/PixelPool{TColor}.cs
  16. 18
      tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs
  17. 24
      tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs
  18. 24
      tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs
  19. 23
      tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs
  20. 29
      tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs
  21. 12
      tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs
  22. 34
      tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
  23. 6
      tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs
  24. 17
      tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs
  25. 6
      tests/ImageSharp.Benchmarks/Image/DecodeGif.cs
  26. 6
      tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs
  27. 6
      tests/ImageSharp.Benchmarks/Image/DecodePng.cs
  28. 8
      tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs
  29. 4
      tests/ImageSharp.Benchmarks/Image/EncodeBmpMultiple.cs
  30. 8
      tests/ImageSharp.Benchmarks/Image/EncodeGif.cs
  31. 8
      tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs
  32. 8
      tests/ImageSharp.Benchmarks/Image/EncodePng.cs
  33. 10
      tests/ImageSharp.Benchmarks/Image/GetSetPixel.cs
  34. 8
      tests/ImageSharp.Benchmarks/Samplers/Crop.cs
  35. 6
      tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
  36. 16
      tests/ImageSharp.Benchmarks/Samplers/Resize.cs
  37. 137
      tests/ImageSharp.Tests/Drawing/BeziersTests.cs
  38. 21
      tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
  39. 101
      tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
  40. 71
      tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
  41. 100
      tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
  42. 226
      tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
  43. 155
      tests/ImageSharp.Tests/Drawing/LineTests.cs
  44. 112
      tests/ImageSharp.Tests/Drawing/PolygonTests.cs
  45. 32
      tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs
  46. 102
      tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs
  47. 138
      tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs
  48. 156
      tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs
  49. 15
      tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs
  50. 101
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  51. 16
      tests/ImageSharp.Tests/Formats/Jpg/BadEofJpegTests.cs
  52. 61
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  53. 44
      tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
  54. 85
      tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs
  55. 4
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.cs
  56. 20
      tests/ImageSharp.Tests/Formats/Png/PngTests.cs
  57. 9
      tests/ImageSharp.Tests/Image/ImageTests.cs
  58. 118
      tests/ImageSharp.Tests/Image/PixelAccessorTests.cs
  59. 20
      tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs
  60. 19
      tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs
  61. 8
      tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs
  62. 10
      tests/ImageSharp.Tests/Processors/Filters/BinaryThreshold.cs
  63. 8
      tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs
  64. 10
      tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs
  65. 10
      tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs
  66. 10
      tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs
  67. 10
      tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs
  68. 8
      tests/ImageSharp.Tests/Processors/Filters/CropTest.cs
  69. 15
      tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs
  70. 10
      tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs
  71. 10
      tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs
  72. 10
      tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs
  73. 10
      tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs
  74. 31
      tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs
  75. 10
      tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs
  76. 10
      tests/ImageSharp.Tests/Processors/Filters/HueTest.cs
  77. 16
      tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs
  78. 8
      tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs
  79. 15
      tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs
  80. 21
      tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs
  81. 8
      tests/ImageSharp.Tests/Processors/Filters/PadTest.cs
  82. 8
      tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs
  83. 8
      tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs
  84. 76
      tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs
  85. 10
      tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs
  86. 20
      tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs
  87. 8
      tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs
  88. 6
      tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs
  89. 12
      tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs
  90. 31
      tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs
  91. 3
      tests/ImageSharp.Tests/Profiles/Exif/ExifProfileTests.cs
  92. 2
      tests/ImageSharp.Tests/Profiles/Exif/ExifTagDescriptionAttributeTests.cs
  93. 7
      tests/ImageSharp.Tests/Profiles/Exif/ExifValueTests.cs

4
src/ImageSharp.Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -54,9 +54,9 @@ namespace ImageSharp.Processing.Processors
int maxY = endY - 1; int maxY = endY - 1;
int maxX = endX - 1; int maxX = endX - 1;
TColor[] target = new TColor[source.Width * source.Height]; TColor[] target = PixelPool<TColor>.RentPixels(source.Width * source.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(source.Width, source.Height)) using (PixelAccessor<TColor> targetPixels = target.Lock(source.Width, source.Height))
{ {
Parallel.For( Parallel.For(
startY, startY,

21
src/ImageSharp.Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -45,13 +45,20 @@ namespace ImageSharp.Processing.Processors
int width = source.Width; int width = source.Width;
int height = source.Height; int height = source.Height;
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
TColor[] firstPass = new TColor[width * height]; TColor[] firstPass = PixelPool<TColor>.RentPixels(width * height);
this.ApplyConvolution(width, height, firstPass, source.Pixels, sourceRectangle, kernelX); try
this.ApplyConvolution(width, height, target, firstPass, sourceRectangle, kernelY); {
this.ApplyConvolution(width, height, firstPass, source.Pixels, sourceRectangle, kernelX);
this.ApplyConvolution(width, height, target, firstPass, sourceRectangle, kernelY);
source.SetPixels(width, height, target); source.SetPixels(width, height, target);
}
finally
{
PixelPool<TColor>.ReturnPixels(firstPass);
}
} }
/// <summary> /// <summary>
@ -80,8 +87,8 @@ namespace ImageSharp.Processing.Processors
int maxY = endY - 1; int maxY = endY - 1;
int maxX = endX - 1; int maxX = endX - 1;
using (PixelAccessor<TColor> sourcePixels = source.Lock<TColor>(width, height)) using (PixelAccessor<TColor> sourcePixels = source.Lock(width, height))
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
startY, startY,

4
src/ImageSharp.Processing/Processors/Effects/OilPaintingProcessor.cs

@ -67,9 +67,9 @@ namespace ImageSharp.Processing.Processors
startX = 0; startX = 0;
} }
TColor[] target = new TColor[source.Width * source.Height]; TColor[] target = PixelPool<TColor>.RentPixels(source.Width * source.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(source.Width, source.Height)) using (PixelAccessor<TColor> targetPixels = target.Lock(source.Width, source.Height))
{ {
Parallel.For( Parallel.For(
minY, minY,

4
src/ImageSharp.Processing/Processors/Effects/PixelateProcessor.cs

@ -63,10 +63,10 @@ namespace ImageSharp.Processing.Processors
// Get the range on the y-plane to choose from. // Get the range on the y-plane to choose from.
IEnumerable<int> range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size); IEnumerable<int> range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size);
TColor[] target = new TColor[source.Width * source.Height]; TColor[] target = PixelPool<TColor>.RentPixels(source.Width * source.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(source.Width, source.Height)) using (PixelAccessor<TColor> targetPixels = target.Lock(source.Width, source.Height))
{ {
Parallel.ForEach( Parallel.ForEach(
range, range,

159
src/ImageSharp.Processing/Processors/Transforms/CompandingResizeProcessor.cs

@ -66,103 +66,112 @@ namespace ImageSharp.Processing.Processors
int minY = Math.Max(0, startY); int minY = Math.Max(0, startY);
int maxY = Math.Min(height, endY); int maxY = Math.Min(height, endY);
TColor[] target = new TColor[width * height]; TColor[] firstPass = null;
if (this.Sampler is NearestNeighborResampler) try
{ {
// Scaling factors TColor[] target = PixelPool<TColor>.RentPixels(width * height);
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; if (this.Sampler is NearestNeighborResampler)
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; {
// Scaling factors
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
// Y coordinates of source points
int originY = (int)((y - startY) * heightFactor);
for (int x = minX; x < maxX; x++)
{
// X coordinates of source points
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY];
}
});
}
// Break out now.
source.SetPixels(width, height, target);
return;
}
// Interpolate the image using the calculated weights.
// 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.
firstPass = PixelPool<TColor>.RentPixels(width * source.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> firstPassPixels = firstPass.Lock(width, source.Height))
using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
minY, 0,
maxY, sourceRectangle.Height,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{ {
// Y coordinates of source points
int originY = (int)((y - startY) * heightFactor);
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
// X coordinates of source points // Ensure offsets are normalised for cropping and padding.
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
}
});
}
// Break out now. // Destination color components
source.SetPixels(width, height, target); Vector4 destination = Vector4.Zero;
return;
}
// Interpolate the image using the calculated weights. for (int i = 0; i < horizontalValues.Length; i++)
// 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 Weight xw = horizontalValues[i];
// are the upper and lower bounds of the source rectangle. destination += sourcePixels[xw.Index, y].ToVector4().Expand() * xw.Value;
TColor[] firstPass = new TColor[width * source.Height]; }
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> firstPassPixels = firstPass.Lock<TColor>(width, source.Height))
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height))
{
Parallel.For(
0,
sourceRectangle.Height,
this.ParallelOptions,
y =>
{
for (int x = minX; x < maxX; x++)
{
// Ensure offsets are normalised for cropping and padding.
Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
// Destination color components TColor d = default(TColor);
Vector4 destination = Vector4.Zero; d.PackFromVector4(destination.Compress());
firstPassPixels[x, y] = d;
for (int i = 0; i < horizontalValues.Length; i++)
{
Weight xw = horizontalValues[i];
destination += sourcePixels[xw.Index, y].ToVector4().Expand() * xw.Value;
} }
});
TColor d = default(TColor); // Now process the rows.
d.PackFromVector4(destination.Compress()); Parallel.For(
firstPassPixels[x, y] = d; minY,
} maxY,
}); this.ParallelOptions,
y =>
// Now process the rows.
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
// Ensure offsets are normalised for cropping and padding.
Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
for (int x = 0; x < width; x++)
{ {
// Destination color components // Ensure offsets are normalised for cropping and padding.
Vector4 destination = Vector4.Zero; Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
for (int i = 0; i < verticalValues.Length; i++) for (int x = 0; x < width; x++)
{ {
Weight yw = verticalValues[i]; // Destination color components
destination += firstPassPixels[x, yw.Index].ToVector4().Expand() * yw.Value; Vector4 destination = Vector4.Zero;
for (int i = 0; i < verticalValues.Length; i++)
{
Weight yw = verticalValues[i];
destination += firstPassPixels[x, yw.Index].ToVector4().Expand() * yw.Value;
}
TColor d = default(TColor);
d.PackFromVector4(destination.Compress());
targetPixels[x, y] = d;
} }
});
}
TColor d = default(TColor); source.SetPixels(width, height, target);
d.PackFromVector4(destination.Compress()); }
targetPixels[x, y] = d; finally
} {
}); // We don't return target or source pixels as they are handled in the image itself.
PixelPool<TColor>.ReturnPixels(firstPass);
} }
source.SetPixels(width, height, target);
} }
} }
} }

4
src/ImageSharp.Processing/Processors/Transforms/CropProcessor.cs

@ -42,10 +42,10 @@ namespace ImageSharp.Processing.Processors
int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X); int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right); int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);
TColor[] target = new TColor[this.CropRectangle.Width * this.CropRectangle.Height]; TColor[] target = PixelPool<TColor>.RentPixels(this.CropRectangle.Width * this.CropRectangle.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(this.CropRectangle.Width, this.CropRectangle.Height)) using (PixelAccessor<TColor> targetPixels = target.Lock(this.CropRectangle.Width, this.CropRectangle.Height))
{ {
Parallel.For( Parallel.For(
minY, minY,

8
src/ImageSharp.Processing/Processors/Transforms/FlipProcessor.cs

@ -55,10 +55,10 @@ namespace ImageSharp.Processing.Processors
int height = source.Height; int height = source.Height;
int halfHeight = (int)Math.Ceiling(source.Height * .5F); int halfHeight = (int)Math.Ceiling(source.Height * .5F);
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
0, 0,
@ -89,10 +89,10 @@ namespace ImageSharp.Processing.Processors
int height = source.Height; int height = source.Height;
int halfWidth = (int)Math.Ceiling(width * .5F); int halfWidth = (int)Math.Ceiling(width * .5F);
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
0, 0,

159
src/ImageSharp.Processing/Processors/Transforms/ResizeProcessor.cs

@ -65,103 +65,112 @@ namespace ImageSharp.Processing.Processors
int minY = Math.Max(0, startY); int minY = Math.Max(0, startY);
int maxY = Math.Min(height, endY); int maxY = Math.Min(height, endY);
TColor[] target = new TColor[width * height]; TColor[] firstPass = null;
if (this.Sampler is NearestNeighborResampler) try
{ {
// Scaling factors TColor[] target = PixelPool<TColor>.RentPixels(width * height);
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; if (this.Sampler is NearestNeighborResampler)
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; {
// Scaling factors
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
// Y coordinates of source points
int originY = (int)((y - startY) * heightFactor);
for (int x = minX; x < maxX; x++)
{
// X coordinates of source points
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY];
}
});
}
// Break out now.
source.SetPixels(width, height, target);
return;
}
// Interpolate the image using the calculated weights.
// 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.
firstPass = PixelPool<TColor>.RentPixels(width * source.Height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> firstPassPixels = firstPass.Lock(width, source.Height))
using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
minY, 0,
maxY, sourceRectangle.Height,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{ {
// Y coordinates of source points
int originY = (int)((y - startY) * heightFactor);
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
// X coordinates of source points // Ensure offsets are normalised for cropping and padding.
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
}
});
}
// Break out now. // Destination color components
source.SetPixels(width, height, target); Vector4 destination = Vector4.Zero;
return;
}
// Interpolate the image using the calculated weights. for (int i = 0; i < horizontalValues.Length; i++)
// 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 Weight xw = horizontalValues[i];
// are the upper and lower bounds of the source rectangle. destination += sourcePixels[xw.Index, y].ToVector4() * xw.Value;
TColor[] firstPass = new TColor[width * source.Height]; }
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> firstPassPixels = firstPass.Lock<TColor>(width, source.Height))
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height))
{
Parallel.For(
0,
sourceRectangle.Height,
this.ParallelOptions,
y =>
{
for (int x = minX; x < maxX; x++)
{
// Ensure offsets are normalised for cropping and padding.
Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
// Destination color components TColor d = default(TColor);
Vector4 destination = Vector4.Zero; d.PackFromVector4(destination);
firstPassPixels[x, y] = d;
for (int i = 0; i < horizontalValues.Length; i++)
{
Weight xw = horizontalValues[i];
destination += sourcePixels[xw.Index, y].ToVector4() * xw.Value;
} }
});
TColor d = default(TColor); // Now process the rows.
d.PackFromVector4(destination); Parallel.For(
firstPassPixels[x, y] = d; minY,
} maxY,
}); this.ParallelOptions,
y =>
// Now process the rows.
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
// Ensure offsets are normalised for cropping and padding.
Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
for (int x = 0; x < width; x++)
{ {
// Destination color components // Ensure offsets are normalised for cropping and padding.
Vector4 destination = Vector4.Zero; Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
for (int i = 0; i < verticalValues.Length; i++) for (int x = 0; x < width; x++)
{ {
Weight yw = verticalValues[i]; // Destination color components
destination += firstPassPixels[x, yw.Index].ToVector4() * yw.Value; Vector4 destination = Vector4.Zero;
for (int i = 0; i < verticalValues.Length; i++)
{
Weight yw = verticalValues[i];
destination += firstPassPixels[x, yw.Index].ToVector4() * yw.Value;
}
TColor d = default(TColor);
d.PackFromVector4(destination);
targetPixels[x, y] = d;
} }
});
}
TColor d = default(TColor); source.SetPixels(width, height, target);
d.PackFromVector4(destination); }
targetPixels[x, y] = d; finally
} {
}); // We don't return target or source pixels as they are handled in the image itself.
PixelPool<TColor>.ReturnPixels(firstPass);
} }
source.SetPixels(width, height, target);
} }
} }
} }

16
src/ImageSharp.Processing/Processors/Transforms/RotateProcessor.cs

@ -42,10 +42,10 @@ namespace ImageSharp.Processing.Processors
int height = this.CanvasRectangle.Height; int height = this.CanvasRectangle.Height;
int width = this.CanvasRectangle.Width; int width = this.CanvasRectangle.Width;
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix); Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
0, 0,
@ -124,10 +124,10 @@ namespace ImageSharp.Processing.Processors
{ {
int width = source.Width; int width = source.Width;
int height = source.Height; int height = source.Height;
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(height, width)) using (PixelAccessor<TColor> targetPixels = target.Lock(height, width))
{ {
Parallel.For( Parallel.For(
0, 0,
@ -156,10 +156,10 @@ namespace ImageSharp.Processing.Processors
{ {
int width = source.Width; int width = source.Width;
int height = source.Height; int height = source.Height;
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
0, 0,
@ -187,10 +187,10 @@ namespace ImageSharp.Processing.Processors
{ {
int width = source.Width; int width = source.Width;
int height = source.Height; int height = source.Height;
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(height, width)) using (PixelAccessor<TColor> targetPixels = target.Lock(height, width))
{ {
Parallel.For( Parallel.For(
0, 0,

4
src/ImageSharp.Processing/Processors/Transforms/SkewProcessor.cs

@ -42,10 +42,10 @@ namespace ImageSharp.Processing.Processors
int height = this.CanvasRectangle.Height; int height = this.CanvasRectangle.Height;
int width = this.CanvasRectangle.Width; int width = this.CanvasRectangle.Width;
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix); Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);
TColor[] target = new TColor[width * height]; TColor[] target = PixelPool<TColor>.RentPixels(width * height);
using (PixelAccessor<TColor> sourcePixels = source.Lock()) using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PixelAccessor<TColor> targetPixels = target.Lock<TColor>(width, height)) using (PixelAccessor<TColor> targetPixels = target.Lock(width, height))
{ {
Parallel.For( Parallel.For(
0, 0,

4
src/ImageSharp/Image/IImageBase{TColor}.cs

@ -11,11 +11,13 @@ namespace ImageSharp
/// Encapsulates the basic properties and methods required to manipulate images in varying formats. /// Encapsulates the basic properties and methods required to manipulate images in varying formats.
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
public interface IImageBase<TColor> : IImageBase public interface IImageBase<TColor> : IImageBase, IDisposable
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
/// <summary> /// <summary>
/// Gets the pixels as an array of the given packed pixel format. /// Gets the pixels as an array of the given packed pixel format.
/// Important. Due to the nature in the way this is constructed do not rely on the length
/// of the array for calculations. Use Width * Height.
/// </summary> /// </summary>
TColor[] Pixels { get; } TColor[] Pixels { get; }

111
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -6,6 +6,7 @@
namespace ImageSharp namespace ImageSharp
{ {
using System; using System;
using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
/// <summary> /// <summary>
@ -14,14 +15,30 @@ namespace ImageSharp
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
[DebuggerDisplay("Image: {Width}x{Height}")] [DebuggerDisplay("Image: {Width}x{Height}")]
public abstract class ImageBase<TColor> : IImageBase<TColor> public abstract class ImageBase<TColor> : IImageBase<TColor> // IImageBase implements IDisposable
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
/// <summary>
/// The <see cref="ArrayPool{TColor}"/> used to pool data. TODO: Choose sensible default size and count
/// </summary>
private static readonly ArrayPool<TColor> ArrayPool = ArrayPool<TColor>.Create(int.MaxValue, 50);
/// <summary> /// <summary>
/// The image pixels /// The image pixels
/// </summary> /// </summary>
private TColor[] pixelBuffer; private TColor[] pixelBuffer;
/// <summary>
/// A value indicating whether this instance of the given entity has been disposed.
/// </summary>
/// <value><see langword="true"/> if this instance has been disposed; otherwise, <see langword="false"/>.</value>
/// <remarks>
/// If the entity is disposed, it must not be disposed a second time. The isDisposed field is set the first time the entity
/// is disposed. If the isDisposed field is true, then the Dispose() method will not dispose again. This help not to prolong the entity's
/// life in the Garbage Collector.
/// </remarks>
private bool isDisposed;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageBase{TColor}"/> class. /// Initializes a new instance of the <see cref="ImageBase{TColor}"/> class.
/// </summary> /// </summary>
@ -41,7 +58,7 @@ namespace ImageSharp
/// <param name="configuration"> /// <param name="configuration">
/// The configuration providing initialization code which allows extending the library. /// The configuration providing initialization code which allows extending the library.
/// </param> /// </param>
/// <exception cref="System.ArgumentOutOfRangeException"> /// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0. /// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0.
/// </exception> /// </exception>
protected ImageBase(int width, int height, Configuration configuration = null) protected ImageBase(int width, int height, Configuration configuration = null)
@ -67,15 +84,24 @@ namespace ImageSharp
this.Height = other.Height; this.Height = other.Height;
this.CopyProperties(other); this.CopyProperties(other);
// Copy the pixels. Unsafe.CopyBlock gives us a nice speed boost here. // Rent then copy the pixels. Unsafe.CopyBlock gives us a nice speed boost here.
this.pixelBuffer = new TColor[this.Width * this.Height]; this.RentPixels();
using (PixelAccessor<TColor> sourcePixels = other.Lock()) using (PixelAccessor<TColor> sourcePixels = other.Lock())
using (PixelAccessor<TColor> target = this.Lock()) using (PixelAccessor<TColor> target = this.Lock())
{ {
// Check we can do this without crashing
sourcePixels.CopyTo(target); sourcePixels.CopyTo(target);
} }
} }
/// <summary>
/// Finalizes an instance of the <see cref="ImageBase{TColor}"/> class.
/// </summary>
~ImageBase()
{
this.Dispose(false);
}
/// <inheritdoc/> /// <inheritdoc/>
public int MaxWidth { get; set; } = int.MaxValue; public int MaxWidth { get; set; } = int.MaxValue;
@ -108,6 +134,19 @@ namespace ImageSharp
/// </summary> /// </summary>
public Configuration Configuration { get; private set; } public Configuration Configuration { get; private set; }
/// <inheritdoc />
public void Dispose()
{
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SuppressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
/// <inheritdoc/> /// <inheritdoc/>
public void InitPixels(int width, int height) public void InitPixels(int width, int height)
{ {
@ -116,7 +155,7 @@ namespace ImageSharp
this.Width = width; this.Width = width;
this.Height = height; this.Height = height;
this.pixelBuffer = new TColor[width * height]; this.RentPixels();
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -126,13 +165,15 @@ namespace ImageSharp
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
Guard.NotNull(pixels, nameof(pixels)); Guard.NotNull(pixels, nameof(pixels));
if (pixels.Length != width * height) if (!(pixels.Length >= width * height))
{ {
throw new ArgumentException("Pixel array must have the length of Width * Height."); throw new ArgumentException($"Pixel array must have the length of at least {width * height}.");
} }
this.Width = width; this.Width = width;
this.Height = height; this.Height = height;
this.ReturnPixels();
this.pixelBuffer = pixels; this.pixelBuffer = pixels;
} }
@ -143,17 +184,18 @@ namespace ImageSharp
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
Guard.NotNull(pixels, nameof(pixels)); Guard.NotNull(pixels, nameof(pixels));
if (pixels.Length != width * height) if (!(pixels.Length >= width * height))
{ {
throw new ArgumentException("Pixel array must have the length of Width * Height."); throw new ArgumentException($"Pixel array must have the length of at least {width * height}.");
} }
this.Width = width; this.Width = width;
this.Height = height; this.Height = height;
// Copy the pixels. TODO: use Unsafe.Copy. // Copy the pixels. TODO: use Unsafe.Copy.
this.pixelBuffer = new TColor[pixels.Length]; this.ReturnPixels();
Array.Copy(pixels, this.pixelBuffer, pixels.Length); this.RentPixels();
Array.Copy(pixels, this.pixelBuffer, width * height);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -174,5 +216,52 @@ namespace ImageSharp
this.Quality = other.Quality; this.Quality = other.Quality;
this.FrameDelay = other.FrameDelay; this.FrameDelay = other.FrameDelay;
} }
/// <summary>
/// Releases any unmanaged resources from the inheriting class.
/// </summary>
protected virtual void ReleaseUnmanagedResources()
{
// TODO release unmanaged resources here
}
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
/// <param name="disposing">If true, the object gets disposed.</param>
protected virtual void Dispose(bool disposing)
{
if (this.isDisposed)
{
return;
}
this.ReleaseUnmanagedResources();
if (disposing)
{
this.ReturnPixels();
}
// Note disposing is done.
this.isDisposed = true;
}
/// <summary>
/// Rents the pixel array from the pool.
/// </summary>
private void RentPixels()
{
this.pixelBuffer = PixelPool<TColor>.RentPixels(this.Width * this.Height);
}
/// <summary>
/// Returns the rented pixel array back to the pool.
/// </summary>
private void ReturnPixels()
{
PixelPool<TColor>.ReturnPixels(this.pixelBuffer);
this.pixelBuffer = null;
}
} }
} }

16
src/ImageSharp/Image/Image{TColor}.cs

@ -334,9 +334,9 @@ namespace ImageSharp
target.ExifProfile = new ExifProfile(this.ExifProfile); target.ExifProfile = new ExifProfile(this.ExifProfile);
} }
foreach (ImageFrame<TColor> frame in this.Frames) for (int i = 0; i < this.Frames.Count; i++)
{ {
target.Frames.Add(frame.To<TColor2>()); target.Frames.Add(this.Frames[i].To<TColor2>());
} }
return target; return target;
@ -372,6 +372,18 @@ namespace ImageSharp
return new ImageFrame<TColor>(this); return new ImageFrame<TColor>(this);
} }
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
// ReSharper disable once ForCanBeConvertedToForeach
for (int i = 0; i < this.Frames.Count; i++)
{
this.Frames[i].Dispose();
}
base.Dispose(disposing);
}
/// <summary> /// <summary>
/// Loads the image from the given stream. /// Loads the image from the given stream.
/// </summary> /// </summary>

4
src/ImageSharp/Image/PixelAccessor{TColor}.cs

@ -76,9 +76,9 @@ namespace ImageSharp
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
if (pixels.Length != width * height) if (!(pixels.Length >= width * height))
{ {
throw new ArgumentException("Pixel array must have the length of Width * Height."); throw new ArgumentException($"Pixel array must have the length of at least {width * height}.");
} }
this.Width = width; this.Width = width;

50
src/ImageSharp/Image/PixelPool{TColor}.cs

@ -0,0 +1,50 @@
// <copyright file="PixelPool{TColor}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Buffers;
/// <summary>
/// Provides a resource pool that enables reusing instances of type <see cref="T:TColor[]"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public static class PixelPool<TColor>
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// The <see cref="ArrayPool{T}"/> used to pool data. TODO: Choose sensible default size and count
/// </summary>
private static readonly ArrayPool<TColor> ArrayPool = ArrayPool<TColor>.Create(int.MaxValue, 50);
/// <summary>
/// Rents the pixel array from the pool.
/// </summary>
/// <param name="minimumLength">The minimum length of the array to return.</param>
/// <returns>The <see cref="T:TColor[]"/></returns>
public static TColor[] RentPixels(int minimumLength)
{
return ArrayPool.Rent(minimumLength);
}
/// <summary>
/// Returns the rented pixel array back to the pool.
/// </summary>
/// <param name="array">The array to return to the buffer pool.</param>
public static void ReturnPixels(TColor[] array)
{
try
{
ArrayPool.Return(array, true);
}
catch
{
// Do nothing.
// Hacky but it allows us to attempt to return non-pooled arrays and arrays that have already been returned
}
}
}
}

18
tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs

@ -47,18 +47,22 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Draw Beziers")] [Benchmark(Description = "ImageSharp Draw Beziers")]
public void DrawLinesCore() public void DrawLinesCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
{
image.DrawBeziers(CoreColor.HotPink, 10, new[] { image.DrawBeziers(
CoreColor.HotPink,
10,
new[] {
new Vector2(10, 500), new Vector2(10, 500),
new Vector2(30, 10), new Vector2(30, 10),
new Vector2(240, 30), new Vector2(240, 30),
new Vector2(300, 500) new Vector2(300, 500)
}); });
using (MemoryStream ms = new MemoryStream()) using (MemoryStream ms = new MemoryStream())
{ {
image.SaveAsBmp(ms); image.SaveAsBmp(ms);
}
} }
} }
} }

24
tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs

@ -46,17 +46,21 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Draw Lines")] [Benchmark(Description = "ImageSharp Draw Lines")]
public void DrawLinesCore() public void DrawLinesCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
image.DrawLines(CoreColor.HotPink, 10, new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{ {
image.SaveAsBmp(ms); image.DrawLines(
CoreColor.HotPink,
10,
new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{
image.SaveAsBmp(ms);
}
} }
} }
} }

24
tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs

@ -45,17 +45,21 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Draw Polygon")] [Benchmark(Description = "ImageSharp Draw Polygon")]
public void DrawPolygonCore() public void DrawPolygonCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
image.DrawPolygon(CoreColor.HotPink, 10, new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{ {
image.SaveAsBmp(ms); image.DrawPolygon(
CoreColor.HotPink,
10,
new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{
image.SaveAsBmp(ms);
}
} }
} }
} }

23
tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs

@ -44,17 +44,20 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Fill Polygon")] [Benchmark(Description = "ImageSharp Fill Polygon")]
public void DrawSolidPolygonCore() public void DrawSolidPolygonCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
image.FillPolygon(CoreColor.HotPink,
new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{ {
image.SaveAsBmp(ms); image.FillPolygon(
CoreColor.HotPink,
new[] {
new Vector2(10, 10),
new Vector2(550, 50),
new Vector2(200, 400)
});
using (MemoryStream ms = new MemoryStream())
{
image.SaveAsBmp(ms);
}
} }
} }
} }

29
tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs

@ -28,7 +28,6 @@ namespace ImageSharp.Benchmarks
{ {
graphics.InterpolationMode = InterpolationMode.Default; graphics.InterpolationMode = InterpolationMode.Default;
graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.SmoothingMode = SmoothingMode.AntiAlias;
var pen = new Pen(Color.HotPink, 10);
graphics.FillRectangle(Brushes.HotPink, new Rectangle(10, 10, 190, 140)); graphics.FillRectangle(Brushes.HotPink, new Rectangle(10, 10, 190, 140));
} }
return destination.Size; return destination.Size;
@ -38,25 +37,29 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Fill Rectangle")] [Benchmark(Description = "ImageSharp Fill Rectangle")]
public CoreSize FillRactangleCore() public CoreSize FillRactangleCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
{
image.Fill(CoreColor.HotPink, new ImageSharp.Drawing.Shapes.RectangularPolygon(new CoreRectangle(10, 10, 190, 140))); image.Fill(CoreColor.HotPink, new ImageSharp.Drawing.Shapes.RectangularPolygon(new CoreRectangle(10, 10, 190, 140)));
return new CoreSize(image.Width, image.Height); return new CoreSize(image.Width, image.Height);
}
} }
[Benchmark(Description = "ImageSharp Fill Rectangle - As Polygon")] [Benchmark(Description = "ImageSharp Fill Rectangle - As Polygon")]
public CoreSize FillPolygonCore() public CoreSize FillPolygonCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
{
image.FillPolygon(CoreColor.HotPink, new[] { image.FillPolygon(
new Vector2(10, 10), CoreColor.HotPink,
new Vector2(200, 10), new[] {
new Vector2(200, 150), new Vector2(10, 10),
new Vector2(10, 150) }); new Vector2(200, 10),
new Vector2(200, 150),
new Vector2(10, 150) });
return new CoreSize(image.Width, image.Height); return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

12
tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs

@ -38,12 +38,14 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Fill with Pattern")] [Benchmark(Description = "ImageSharp Fill with Pattern")]
public void DrawPatternPolygon3Core() public void DrawPatternPolygon3Core()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
image.Fill(CoreBrushes.BackwardDiagonal(CoreColor.HotPink));
using (MemoryStream ms = new MemoryStream())
{ {
image.SaveAsBmp(ms); image.Fill(CoreBrushes.BackwardDiagonal(CoreColor.HotPink));
using (MemoryStream ms = new MemoryStream())
{
image.SaveAsBmp(ms);
}
} }
} }
} }

34
tests/ImageSharp.Benchmarks/Image/CopyPixels.cs

@ -17,24 +17,26 @@ namespace ImageSharp.Benchmarks.Image
[Benchmark(Description = "Copy by Pixel")] [Benchmark(Description = "Copy by Pixel")]
public CoreColor CopyByPixel() public CoreColor CopyByPixel()
{ {
CoreImage source = new CoreImage(1024, 768); using (CoreImage source = new CoreImage(1024, 768))
CoreImage target = new CoreImage(1024, 768); using (CoreImage target = new CoreImage(1024, 768))
using (PixelAccessor<CoreColor> sourcePixels = source.Lock())
using (PixelAccessor<CoreColor> targetPixels = target.Lock())
{ {
Parallel.For( using (PixelAccessor<CoreColor> sourcePixels = source.Lock())
0, using (PixelAccessor<CoreColor> targetPixels = target.Lock())
source.Height, {
Configuration.Default.ParallelOptions, Parallel.For(
y => 0,
{ source.Height,
for (int x = 0; x < source.Width; x++) Configuration.Default.ParallelOptions,
{ y =>
targetPixels[x, y] = sourcePixels[x, y]; {
} for (int x = 0; x < source.Width; x++)
}); {
targetPixels[x, y] = sourcePixels[x, y];
}
});
return targetPixels[0, 0]; return targetPixels[0, 0];
}
} }
} }
} }

6
tests/ImageSharp.Benchmarks/Image/DecodeBmp.cs

@ -43,8 +43,10 @@ namespace ImageSharp.Benchmarks.Image
{ {
using (MemoryStream memoryStream = new MemoryStream(this.bmpBytes)) using (MemoryStream memoryStream = new MemoryStream(this.bmpBytes))
{ {
CoreImage image = new CoreImage(memoryStream); using (CoreImage image = new CoreImage(memoryStream))
return new CoreSize(image.Width, image.Height); {
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

17
tests/ImageSharp.Benchmarks/Image/DecodeFilteredPng.cs

@ -29,37 +29,40 @@ namespace ImageSharp.Benchmarks.Image
this.filter4 = new MemoryStream(File.ReadAllBytes("../ImageSharp.Tests/TestImages/Formats/Png/filter4.png")); this.filter4 = new MemoryStream(File.ReadAllBytes("../ImageSharp.Tests/TestImages/Formats/Png/filter4.png"));
} }
private Image LoadPng(MemoryStream stream) private Size LoadPng(MemoryStream stream)
{ {
return new Image(stream); using (Image image = new Image(stream))
{
return new Size(image.Width, image.Height);
}
} }
[Benchmark(Baseline = true, Description = "None-filtered PNG file")] [Benchmark(Baseline = true, Description = "None-filtered PNG file")]
public Image PngFilter0() public Size PngFilter0()
{ {
return LoadPng(filter0); return LoadPng(filter0);
} }
[Benchmark(Description = "Sub-filtered PNG file")] [Benchmark(Description = "Sub-filtered PNG file")]
public Image PngFilter1() public Size PngFilter1()
{ {
return LoadPng(filter1); return LoadPng(filter1);
} }
[Benchmark(Description = "Up-filtered PNG file")] [Benchmark(Description = "Up-filtered PNG file")]
public Image PngFilter2() public Size PngFilter2()
{ {
return LoadPng(filter2); return LoadPng(filter2);
} }
[Benchmark(Description = "Average-filtered PNG file")] [Benchmark(Description = "Average-filtered PNG file")]
public Image PngFilter3() public Size PngFilter3()
{ {
return LoadPng(filter3); return LoadPng(filter3);
} }
[Benchmark(Description = "Paeth-filtered PNG file")] [Benchmark(Description = "Paeth-filtered PNG file")]
public Image PngFilter4() public Size PngFilter4()
{ {
return LoadPng(filter4); return LoadPng(filter4);
} }

6
tests/ImageSharp.Benchmarks/Image/DecodeGif.cs

@ -43,8 +43,10 @@ namespace ImageSharp.Benchmarks.Image
{ {
using (MemoryStream memoryStream = new MemoryStream(this.gifBytes)) using (MemoryStream memoryStream = new MemoryStream(this.gifBytes))
{ {
CoreImage image = new CoreImage(memoryStream); using (CoreImage image = new CoreImage(memoryStream))
return new CoreSize(image.Width, image.Height); {
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

6
tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs

@ -43,8 +43,10 @@ namespace ImageSharp.Benchmarks.Image
{ {
using (MemoryStream memoryStream = new MemoryStream(this.jpegBytes)) using (MemoryStream memoryStream = new MemoryStream(this.jpegBytes))
{ {
CoreImage image = new CoreImage(memoryStream); using (CoreImage image = new CoreImage(memoryStream))
return new CoreSize(image.Width, image.Height); {
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

6
tests/ImageSharp.Benchmarks/Image/DecodePng.cs

@ -43,8 +43,10 @@ namespace ImageSharp.Benchmarks.Image
{ {
using (MemoryStream memoryStream = new MemoryStream(this.pngBytes)) using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
{ {
CoreImage image = new CoreImage(memoryStream); using (CoreImage image = new CoreImage(memoryStream))
return new CoreSize(image.Width, image.Height); {
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

8
tests/ImageSharp.Benchmarks/Image/EncodeBmp.cs

@ -31,6 +31,14 @@ namespace ImageSharp.Benchmarks.Image
} }
} }
[Cleanup]
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
[Benchmark(Baseline = true, Description = "System.Drawing Bmp")] [Benchmark(Baseline = true, Description = "System.Drawing Bmp")]
public void BmpSystemDrawing() public void BmpSystemDrawing()
{ {

4
tests/ImageSharp.Benchmarks/Image/EncodeBmpMultiple.cs

@ -18,7 +18,7 @@ namespace ImageSharp.Benchmarks.Image
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" }; protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" };
[Benchmark(Description = "EncodeBmpMultiple - ImageSharp")] [Benchmark(Description = "EncodeBmpMultiple - ImageSharp")]
public void EncodeGifImageSharp() public void EncodeBmpImageSharp()
{ {
this.ForEachImageSharpImage( this.ForEachImageSharpImage(
(img, ms) => (img, ms) =>
@ -29,7 +29,7 @@ namespace ImageSharp.Benchmarks.Image
} }
[Benchmark(Baseline = true, Description = "EncodeBmpMultiple - System.Drawing")] [Benchmark(Baseline = true, Description = "EncodeBmpMultiple - System.Drawing")]
public void EncodeGifSystemDrawing() public void EncodeBmpSystemDrawing()
{ {
this.ForEachSystemDrawingImage( this.ForEachSystemDrawingImage(
(img, ms) => (img, ms) =>

8
tests/ImageSharp.Benchmarks/Image/EncodeGif.cs

@ -31,6 +31,14 @@ namespace ImageSharp.Benchmarks.Image
} }
} }
[Cleanup]
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
[Benchmark(Baseline = true, Description = "System.Drawing Gif")] [Benchmark(Baseline = true, Description = "System.Drawing Gif")]
public void GifSystemDrawing() public void GifSystemDrawing()
{ {

8
tests/ImageSharp.Benchmarks/Image/EncodeJpeg.cs

@ -31,6 +31,14 @@ namespace ImageSharp.Benchmarks.Image
} }
} }
[Cleanup]
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
[Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] [Benchmark(Baseline = true, Description = "System.Drawing Jpeg")]
public void JpegSystemDrawing() public void JpegSystemDrawing()
{ {

8
tests/ImageSharp.Benchmarks/Image/EncodePng.cs

@ -31,6 +31,14 @@ namespace ImageSharp.Benchmarks.Image
} }
} }
[Cleanup]
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
[Benchmark(Baseline = true, Description = "System.Drawing Png")] [Benchmark(Baseline = true, Description = "System.Drawing Png")]
public void PngSystemDrawing() public void PngSystemDrawing()
{ {

10
tests/ImageSharp.Benchmarks/Image/GetSetPixel.cs

@ -28,11 +28,13 @@ namespace ImageSharp.Benchmarks.Image
[Benchmark(Description = "ImageSharp GetSet pixel")] [Benchmark(Description = "ImageSharp GetSet pixel")]
public CoreColor ResizeCore() public CoreColor ResizeCore()
{ {
CoreImage image = new CoreImage(400, 400); using (CoreImage image = new CoreImage(400, 400))
using (PixelAccessor<CoreColor> imagePixels = image.Lock())
{ {
imagePixels[200, 200] = CoreColor.White; using (PixelAccessor<CoreColor> imagePixels = image.Lock())
return imagePixels[200, 200]; {
imagePixels[200, 200] = CoreColor.White;
return imagePixels[200, 200];
}
} }
} }
} }

8
tests/ImageSharp.Benchmarks/Samplers/Crop.cs

@ -38,9 +38,11 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Crop")] [Benchmark(Description = "ImageSharp Crop")]
public CoreSize CropResizeCore() public CoreSize CropResizeCore()
{ {
CoreImage image = new CoreImage(800, 800); using (CoreImage image = new CoreImage(800, 800))
image.Crop(100, 100); {
return new CoreSize(image.Width, image.Height); image.Crop(100, 100);
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

6
tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs

@ -28,6 +28,12 @@ namespace ImageSharp.Benchmarks
} }
} }
[Cleanup]
public void Cleanup()
{
this.image.Dispose();
}
[Benchmark(Description = "ImageSharp DetectEdges")] [Benchmark(Description = "ImageSharp DetectEdges")]
public void ImageProcessorCoreDetectEdges() public void ImageProcessorCoreDetectEdges()
{ {

16
tests/ImageSharp.Benchmarks/Samplers/Resize.cs

@ -37,17 +37,21 @@ namespace ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp Resize")] [Benchmark(Description = "ImageSharp Resize")]
public CoreSize ResizeCore() public CoreSize ResizeCore()
{ {
CoreImage image = new CoreImage(2000, 2000); using (CoreImage image = new CoreImage(2000, 2000))
image.Resize(400, 400); {
return new CoreSize(image.Width, image.Height); image.Resize(400, 400);
return new CoreSize(image.Width, image.Height);
}
} }
[Benchmark(Description = "ImageSharp Compand Resize")] [Benchmark(Description = "ImageSharp Compand Resize")]
public CoreSize ResizeCoreCompand() public CoreSize ResizeCoreCompand()
{ {
CoreImage image = new CoreImage(2000, 2000); using (CoreImage image = new CoreImage(2000, 2000))
image.Resize(400, 400, true); {
return new CoreSize(image.Width, image.Height); image.Resize(400, 400, true);
return new CoreSize(image.Width, image.Height);
}
} }
} }
} }

137
tests/ImageSharp.Tests/Drawing/BeziersTests.cs

@ -15,89 +15,88 @@ namespace ImageSharp.Tests.Drawing
public class Beziers : FileTestBase public class Beziers : FileTestBase
{ {
[Fact] [Fact]
public void ImageShouldBeOverlayedByBezierLine() public void ImageShouldBeOverlayedByBezierLine()
{ {
string path = CreateOutputDirectory("Drawing","BezierLine"); string path = this.CreateOutputDirectory("Drawing", "BezierLine");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{
image
.BackgroundColor(Color.Blue)
.DrawBeziers(Color.HotPink, 5, new[] {
new Vector2(10, 400),
new Vector2(30, 10),
new Vector2(240, 30),
new Vector2(300, 400)
})
.Save(output);
}
using (var sourcePixels = image.Lock())
{ {
//top of curve using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
Assert.Equal(Color.HotPink, sourcePixels[138,115]); {
image.BackgroundColor(Color.Blue)
//start points .DrawBeziers(Color.HotPink, 5,
Assert.Equal(Color.HotPink, sourcePixels[10, 400]); new[] {
Assert.Equal(Color.HotPink, sourcePixels[300, 400]); new Vector2(10, 400),
new Vector2(30, 10),
//curve points should not be never be set new Vector2(240, 30),
Assert.Equal(Color.Blue, sourcePixels[30, 10]); new Vector2(300, 400)
Assert.Equal(Color.Blue, sourcePixels[240, 30]); })
.Save(output);
// inside shape should be empty }
Assert.Equal(Color.Blue, sourcePixels[200, 250]);
using (PixelAccessor<Color> sourcePixels = image.Lock())
{
//top of curve
Assert.Equal(Color.HotPink, sourcePixels[138, 115]);
//start points
Assert.Equal(Color.HotPink, sourcePixels[10, 400]);
Assert.Equal(Color.HotPink, sourcePixels[300, 400]);
//curve points should not be never be set
Assert.Equal(Color.Blue, sourcePixels[30, 10]);
Assert.Equal(Color.Blue, sourcePixels[240, 30]);
// inside shape should be empty
Assert.Equal(Color.Blue, sourcePixels[200, 250]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedBezierLineWithOpacity() public void ImageShouldBeOverlayedBezierLineWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "BezierLine"); string path = this.CreateOutputDirectory("Drawing", "BezierLine");
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.DrawBeziers(color, 10, new[] { image.BackgroundColor(Color.Blue)
new Vector2(10, 400), .DrawBeziers(color,
new Vector2(30, 10), 10,
new Vector2(240, 30), new[] {
new Vector2(300, 400) new Vector2(10, 400),
}) new Vector2(30, 10),
.Save(output); new Vector2(240, 30),
new Vector2(300, 400)
})
.Save(output);
}
//shift background color towards forground color by the opacity amount
Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (PixelAccessor<Color> sourcePixels = image.Lock())
{
//top of curve
Assert.Equal(mergedColor, sourcePixels[138, 115]);
//start points
Assert.Equal(mergedColor, sourcePixels[10, 400]);
Assert.Equal(mergedColor, sourcePixels[300, 400]);
//curve points should not be never be set
Assert.Equal(Color.Blue, sourcePixels[30, 10]);
Assert.Equal(Color.Blue, sourcePixels[240, 30]);
// inside shape should be empty
Assert.Equal(Color.Blue, sourcePixels[200, 250]);
}
} }
}
//shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f/255f));
using (var sourcePixels = image.Lock())
{
//top of curve
Assert.Equal(mergedColor, sourcePixels[138, 115]);
//start points
Assert.Equal(mergedColor, sourcePixels[10, 400]);
Assert.Equal(mergedColor, sourcePixels[300, 400]);
//curve points should not be never be set
Assert.Equal(Color.Blue, sourcePixels[30, 10]);
Assert.Equal(Color.Blue, sourcePixels[240, 30]);
// inside shape should be empty
Assert.Equal(Color.Blue, sourcePixels[200, 250]);
}
}
} }
} }

21
tests/ImageSharp.Tests/Drawing/DrawImageTest.cs

@ -6,7 +6,6 @@
namespace ImageSharp.Tests namespace ImageSharp.Tests
{ {
using System.IO; using System.IO;
using System.Linq;
using Xunit; using Xunit;
@ -15,18 +14,20 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyDrawImageFilter() public void ImageShouldApplyDrawImageFilter()
{ {
string path = CreateOutputDirectory("Drawing", "DrawImage"); string path = this.CreateOutputDirectory("Drawing", "DrawImage");
Image blend = TestFile.Create(TestImages.Bmp.Car).CreateImage(); using (Image blend = TestFile.Create(TestImages.Bmp.Car).CreateImage())
foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); foreach (TestFile file in Files)
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.DrawImage(blend, 75, new Size(image.Width / 2, image.Height / 2), new Point(image.Width / 4, image.Height / 4)) using (Image image = file.CreateImage())
.Save(output); {
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{
image.DrawImage(blend, 75, new Size(image.Width / 2, image.Height / 2), new Point(image.Width / 4, image.Height / 4))
.Save(output);
}
}
} }
} }
} }

101
tests/ImageSharp.Tests/Drawing/DrawPathTests.cs

@ -20,81 +20,82 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPath() public void ImageShouldBeOverlayedByPath()
{ {
string path = CreateOutputDirectory("Drawing", "Path"); string path = this.CreateOutputDirectory("Drawing", "Path");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
var linerSegemnt = new LinearLineSegment(
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300));
var bazierSegment = new BezierLineSegment(new Vector2(50, 300),
new Vector2(500, 500),
new Vector2(60, 10),
new Vector2(10, 400));
var p = new CorePath(linerSegemnt, bazierSegment);
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{
image
.BackgroundColor(Color.Blue)
.DrawPath(Color.HotPink, 5, p)
.Save(output);
}
using (var sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); LinearLineSegment linerSegemnt = new LinearLineSegment(
new Vector2(10, 10),
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); new Vector2(200, 150),
new Vector2(50, 300));
Assert.Equal(Color.Blue, sourcePixels[50, 50]); BezierLineSegment bazierSegment = new BezierLineSegment(new Vector2(50, 300),
new Vector2(500, 500),
new Vector2(60, 10),
new Vector2(10, 400));
CorePath p = new CorePath(linerSegemnt, bazierSegment);
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{
image
.BackgroundColor(Color.Blue)
.DrawPath(Color.HotPink, 5, p)
.Save(output);
}
using (PixelAccessor<Color> sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedPathWithOpacity() public void ImageShouldBeOverlayedPathWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "Path"); string path = this.CreateOutputDirectory("Drawing", "Path");
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var linerSegemnt = new LinearLineSegment( LinearLineSegment linerSegemnt = new LinearLineSegment(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
); );
var bazierSegment = new BezierLineSegment(new Vector2(50, 300),
BezierLineSegment bazierSegment = new BezierLineSegment(new Vector2(50, 300),
new Vector2(500, 500), new Vector2(500, 500),
new Vector2(60, 10), new Vector2(60, 10),
new Vector2(10, 400)); new Vector2(10, 400));
var p = new CorePath(linerSegemnt, bazierSegment); CorePath p = new CorePath(linerSegemnt, bazierSegment);
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.DrawPath(color, 10, p) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPath(color, 10, p)
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[9, 9]); Assert.Equal(mergedColor, sourcePixels[9, 9]);
Assert.Equal(mergedColor, sourcePixels[199, 149]); Assert.Equal(mergedColor, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
} }
} }

71
tests/ImageSharp.Tests/Drawing/FillPatternTests.cs

@ -15,55 +15,56 @@ namespace ImageSharp.Tests.Drawing
public class FillPatternBrushTests : FileTestBase public class FillPatternBrushTests : FileTestBase
{ {
private Image Test(string name, Color background, IBrush<Color> brush, Color[,] expectedPattern) private void Test(string name, Color background, IBrush<Color> brush, Color[,] expectedPattern)
{ {
string path = CreateOutputDirectory("Fill", "PatternBrush"); string path = this.CreateOutputDirectory("Fill", "PatternBrush");
Image image = new Image(20, 20); using (Image image = new Image(20, 20))
image
.Fill(background)
.Fill(brush);
using (FileStream output = File.OpenWrite($"{path}/{name}.png"))
{
image.Save(output);
}
using (var sourcePixels = image.Lock())
{ {
// lets pick random spots to start checking image
var r = new Random(); .Fill(background)
var xStride = expectedPattern.GetLength(1); .Fill(brush);
var yStride = expectedPattern.GetLength(0);
var offsetX = r.Next(image.Width / xStride) * xStride; using (FileStream output = File.OpenWrite($"{path}/{name}.png"))
var offsetY = r.Next(image.Height / yStride) * yStride;
for (var x = 0; x < xStride; x++)
{ {
for (var y = 0; y < yStride; y++) image.Save(output);
}
using (PixelAccessor<Color> sourcePixels = image.Lock())
{
// lets pick random spots to start checking
Random r = new Random();
int xStride = expectedPattern.GetLength(1);
int yStride = expectedPattern.GetLength(0);
int offsetX = r.Next(image.Width / xStride) * xStride;
int offsetY = r.Next(image.Height / yStride) * yStride;
for (int x = 0; x < xStride; x++)
{ {
var actualX = x + offsetX; for (int y = 0; y < yStride; y++)
var actualY = y + offsetY;
var expected = expectedPattern[y, x]; // inverted pattern
var actual = sourcePixels[actualX, actualY];
if (expected != actual)
{ {
Assert.True(false, $"Expected {expected} but found {actual} at ({actualX},{actualY})"); int actualX = x + offsetX;
int actualY = y + offsetY;
Color expected = expectedPattern[y, x]; // inverted pattern
Color actual = sourcePixels[actualX, actualY];
if (expected != actual)
{
Assert.True(false, $"Expected {expected} but found {actual} at ({actualX},{actualY})");
}
} }
} }
} }
using (FileStream output = File.OpenWrite($"{path}/{name}x4.png"))
{
image.Resize(80, 80).Save(output);
}
} }
using (FileStream output = File.OpenWrite($"{path}/{name}x4.png"))
{
image.Resize(80, 80).Save(output);
}
return image;
} }
[Fact] [Fact]
public void ImageShouldBeFloodFilledWithPercent10() public void ImageShouldBeFloodFilledWithPercent10()
{ {
Test("Percent10", Color.Blue, Brushes.Percent10(Color.HotPink, Color.LimeGreen), new Color[,] { this.Test("Percent10", Color.Blue, Brushes.Percent10(Color.HotPink, Color.LimeGreen),
new[,]
{
{ Color.HotPink , Color.LimeGreen, Color.LimeGreen, Color.LimeGreen}, { Color.HotPink , Color.LimeGreen, Color.LimeGreen, Color.LimeGreen},
{ Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen}, { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen},
{ Color.LimeGreen, Color.LimeGreen, Color.HotPink , Color.LimeGreen}, { Color.LimeGreen, Color.LimeGreen, Color.HotPink , Color.LimeGreen},

100
tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs

@ -18,71 +18,73 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeFloodFilledWithColorOnDefaultBackground() public void ImageShouldBeFloodFilledWithColorOnDefaultBackground()
{ {
string path = CreateOutputDirectory("Fill", "SolidBrush"); string path = this.CreateOutputDirectory("Fill", "SolidBrush");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/DefaultBack.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/DefaultBack.png"))
.Fill(Color.HotPink) {
.Save(output); image
} .Fill(Color.HotPink)
.Save(output);
using (var sourcePixels = image.Lock()) }
{
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); using (PixelAccessor<Color> sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeFloodFilledWithColor() public void ImageShouldBeFloodFilledWithColor()
{ {
string path = CreateOutputDirectory("Fill", "SolidBrush"); string path = this.CreateOutputDirectory("Fill", "SolidBrush");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.Fill(Color.HotPink) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(Color.HotPink)
.Save(output);
using (var sourcePixels = image.Lock()) }
{
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); using (PixelAccessor<Color> sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeFloodFilledWithColorOpacity() public void ImageShouldBeFloodFilledWithColorOpacity()
{ {
string path = CreateOutputDirectory("Fill", "SolidBrush"); string path = this.CreateOutputDirectory("Fill", "SolidBrush");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{
image
.BackgroundColor(Color.Blue)
.Fill(color)
.Save(output);
}
//shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[9, 9]); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
Assert.Equal(mergedColor, sourcePixels[199, 149]);
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{
image
.BackgroundColor(Color.Blue)
.Fill(color)
.Save(output);
}
//shift background color towards forground color by the opacity amount
Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (PixelAccessor<Color> sourcePixels = image.Lock())
{
Assert.Equal(mergedColor, sourcePixels[9, 9]);
Assert.Equal(mergedColor, sourcePixels[199, 149]);
}
} }
} }
} }

226
tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs

@ -5,12 +5,9 @@
namespace ImageSharp.Tests.Drawing namespace ImageSharp.Tests.Drawing
{ {
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using Xunit; using Xunit;
using Drawing;
using ImageSharp.Drawing;
using System.Numerics; using System.Numerics;
using ImageSharp.Drawing.Shapes; using ImageSharp.Drawing.Shapes;
using ImageSharp.Drawing.Pens; using ImageSharp.Drawing.Pens;
@ -20,98 +17,100 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutline() public void ImageShouldBeOverlayedByPolygonOutline()
{ {
string path = CreateOutputDirectory("Drawing", "LineComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "LineComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(93, 85), new Vector2(93, 85),
new Vector2(65, 137)); new Vector2(65, 137));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[10, 10]); Assert.Equal(Color.HotPink, sourcePixels[10, 10]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 300]); Assert.Equal(Color.HotPink, sourcePixels[50, 300]);
Assert.Equal(Color.HotPink, sourcePixels[37, 85]); Assert.Equal(Color.HotPink, sourcePixels[37, 85]);
Assert.Equal(Color.HotPink, sourcePixels[93, 85]); Assert.Equal(Color.HotPink, sourcePixels[93, 85]);
Assert.Equal(Color.HotPink, sourcePixels[65, 137]); Assert.Equal(Color.HotPink, sourcePixels[65, 137]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
//inside shape //inside shape
Assert.Equal(Color.Blue, sourcePixels[100, 192]); Assert.Equal(Color.Blue, sourcePixels[100, 192]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutlineNoOverlapping() public void ImageShouldBeOverlayedByPolygonOutlineNoOverlapping()
{ {
string path = CreateOutputDirectory("Drawing", "LineComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "LineComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(207, 25), new Vector2(207, 25),
new Vector2(263, 25), new Vector2(263, 25),
new Vector2(235, 57)); new Vector2(235, 57));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/SimpleVanishHole.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/SimpleVanishHole.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[10, 10]); Assert.Equal(Color.HotPink, sourcePixels[10, 10]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 300]); Assert.Equal(Color.HotPink, sourcePixels[50, 300]);
//Assert.Equal(Color.HotPink, sourcePixels[37, 85]); //Assert.Equal(Color.HotPink, sourcePixels[37, 85]);
//Assert.Equal(Color.HotPink, sourcePixels[93, 85]); //Assert.Equal(Color.HotPink, sourcePixels[93, 85]);
//Assert.Equal(Color.HotPink, sourcePixels[65, 137]); //Assert.Equal(Color.HotPink, sourcePixels[65, 137]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
//inside shape //inside shape
Assert.Equal(Color.Blue, sourcePixels[100, 192]); Assert.Equal(Color.Blue, sourcePixels[100, 192]);
}
} }
} }
@ -119,44 +118,45 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutlineOverlapping() public void ImageShouldBeOverlayedByPolygonOutlineOverlapping()
{ {
string path = CreateOutputDirectory("Drawing", "LineComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "LineComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(130, 40), new Vector2(130, 40),
new Vector2(65, 137)); new Vector2(65, 137));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/SimpleOverlapping.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/SimpleOverlapping.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(Color.HotPink, 5, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[10, 10]); Assert.Equal(Color.HotPink, sourcePixels[10, 10]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 300]); Assert.Equal(Color.HotPink, sourcePixels[50, 300]);
Assert.Equal(Color.Blue, sourcePixels[130, 41]); Assert.Equal(Color.Blue, sourcePixels[130, 41]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole Assert.Equal(Color.Blue, sourcePixels[2, 2]);
Assert.Equal(Color.Blue, sourcePixels[57, 99]);
//inside shape //inside hole
Assert.Equal(Color.Blue, sourcePixels[100, 192]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
//inside shape
Assert.Equal(Color.Blue, sourcePixels[100, 192]);
}
} }
} }
@ -164,25 +164,26 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutlineDashed() public void ImageShouldBeOverlayedByPolygonOutlineDashed()
{ {
string path = CreateOutputDirectory("Drawing", "LineComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "LineComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(93, 85), new Vector2(93, 85),
new Vector2(65, 137)); new Vector2(65, 137));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Pens.Dash(Color.HotPink, 5), new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
.DrawPolygon(Pens.Dash(Color.HotPink, 5), new ComplexPolygon(simplePath, hole1))
.Save(output);
}
} }
} }
@ -190,54 +191,55 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() public void ImageShouldBeOverlayedPolygonOutlineWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "LineComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "LineComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(93, 85), new Vector2(93, 85),
new Vector2(65, 137)); new Vector2(65, 137));
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(color, 5, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(color, 5, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[10, 10]); Assert.Equal(mergedColor, sourcePixels[10, 10]);
Assert.Equal(mergedColor, sourcePixels[200, 150]); Assert.Equal(mergedColor, sourcePixels[200, 150]);
Assert.Equal(mergedColor, sourcePixels[50, 300]); Assert.Equal(mergedColor, sourcePixels[50, 300]);
Assert.Equal(mergedColor, sourcePixels[37, 85]); Assert.Equal(mergedColor, sourcePixels[37, 85]);
Assert.Equal(mergedColor, sourcePixels[93, 85]); Assert.Equal(mergedColor, sourcePixels[93, 85]);
Assert.Equal(mergedColor, sourcePixels[65, 137]); Assert.Equal(mergedColor, sourcePixels[65, 137]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
//inside shape //inside shape
Assert.Equal(Color.Blue, sourcePixels[100, 192]); Assert.Equal(Color.Blue, sourcePixels[100, 192]);
}
} }
} }
} }

155
tests/ImageSharp.Tests/Drawing/LineTests.cs

@ -5,11 +5,9 @@
namespace ImageSharp.Tests.Drawing namespace ImageSharp.Tests.Drawing
{ {
using Drawing;
using ImageSharp.Drawing; using ImageSharp.Drawing;
using ImageSharp.Drawing.Pens; using ImageSharp.Drawing.Pens;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using Xunit; using Xunit;
@ -19,123 +17,132 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPath() public void ImageShouldBeOverlayedByPath()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.DrawLines(Color.HotPink, 5, new[] { image
.BackgroundColor(Color.Blue)
.DrawLines(Color.HotPink, 5,
new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}) })
.Save(output); .Save(output);
} }
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPath_NoAntialias() public void ImageShouldBeOverlayedByPath_NoAntialias()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple_noantialias.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple_noantialias.png"))
.BackgroundColor(Color.Blue) {
.DrawLines(Color.HotPink, 5, new[] { image
.BackgroundColor(Color.Blue)
.DrawLines(Color.HotPink, 5,
new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}, new GraphicsOptions(false)) },
.Save(output); new GraphicsOptions(false))
} .Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPathDashed() public void ImageShouldBeOverlayedByPathDashed()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
.BackgroundColor(Color.Blue) {
.DrawLines(Pens.Dash(Color.HotPink, 5), new[] { image
.BackgroundColor(Color.Blue)
.DrawLines(Pens.Dash(Color.HotPink, 5),
new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}) })
.Save(output); .Save(output);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPathDotted() public void ImageShouldBeOverlayedByPathDotted()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Dot.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Dot.png"))
.BackgroundColor(Color.Blue) {
.DrawLines(Pens.Dot(Color.HotPink, 5), new[] { image
.BackgroundColor(Color.Blue)
.DrawLines(Pens.Dot(Color.HotPink, 5),
new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}) })
.Save(output); .Save(output);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPathDashDot() public void ImageShouldBeOverlayedByPathDashDot()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/DashDot.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/DashDot.png"))
.BackgroundColor(Color.Blue) {
.DrawLines(Pens.DashDot(Color.HotPink, 5), new[] { image
.BackgroundColor(Color.Blue)
.DrawLines(Pens.DashDot(Color.HotPink, 5),
new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}) })
.Save(output); .Save(output);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByPathDashDotDot() public void ImageShouldBeOverlayedByPathDashDotDot()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); Image image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/DashDotDot.png")) using (FileStream output = File.OpenWrite($"{path}/DashDotDot.png"))
{ {
@ -153,12 +160,12 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedPathWithOpacity() public void ImageShouldBeOverlayedPathWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
Image image = new Image(500, 500);
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Opacity.png")) using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
@ -173,9 +180,9 @@ namespace ImageSharp.Tests.Drawing
} }
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f/255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f/255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[9, 9]); Assert.Equal(mergedColor, sourcePixels[9, 9]);
@ -188,9 +195,9 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPathOutline() public void ImageShouldBeOverlayedByPathOutline()
{ {
string path = CreateOutputDirectory("Drawing", "Lines"); string path = this.CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500); Image image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Rectangle.png")) using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
{ {
@ -205,7 +212,7 @@ namespace ImageSharp.Tests.Drawing
.Save(output); .Save(output);
} }
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[8, 8]); Assert.Equal(Color.HotPink, sourcePixels[8, 8]);
@ -216,6 +223,6 @@ namespace ImageSharp.Tests.Drawing
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
} }
} }
} }
} }

112
tests/ImageSharp.Tests/Drawing/PolygonTests.cs

@ -18,97 +18,101 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutline() public void ImageShouldBeOverlayedByPolygonOutline()
{ {
string path = CreateOutputDirectory("Drawing", "Polygons"); string path = this.CreateOutputDirectory("Drawing", "Polygons");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Color.HotPink, 5, new[] { image
new Vector2(10, 10), .BackgroundColor(Color.Blue)
new Vector2(200, 150), .DrawPolygon(Color.HotPink, 5,
new Vector2(50, 300) new[] {
}) new Vector2(10, 10),
.Save(output); new Vector2(200, 150),
} new Vector2(50, 300)
})
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[9, 9]); Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]); Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() public void ImageShouldBeOverlayedPolygonOutlineWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "Polygons"); string path = this.CreateOutputDirectory("Drawing", "Polygons");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}; };
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(color, 10, simplePath) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(color, 10, simplePath)
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[9, 9]); Assert.Equal(mergedColor, sourcePixels[9, 9]);
Assert.Equal(mergedColor, sourcePixels[199, 149]); Assert.Equal(mergedColor, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByRectangleOutline() public void ImageShouldBeOverlayedByRectangleOutline()
{ {
string path = CreateOutputDirectory("Drawing", "Polygons"); string path = this.CreateOutputDirectory("Drawing", "Polygons");
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
.BackgroundColor(Color.Blue) {
.DrawPolygon(Color.HotPink, 10, new Rectangle(10, 10, 190, 140)) image
.Save(output); .BackgroundColor(Color.Blue)
} .DrawPolygon(Color.HotPink, 10, new Rectangle(10, 10, 190, 140))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[8, 8]); Assert.Equal(Color.HotPink, sourcePixels[8, 8]);
Assert.Equal(Color.HotPink, sourcePixels[198, 10]); Assert.Equal(Color.HotPink, sourcePixels[198, 10]);
Assert.Equal(Color.HotPink, sourcePixels[10, 50]); Assert.Equal(Color.HotPink, sourcePixels[10, 50]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]); Assert.Equal(Color.Blue, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
} }

32
tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs

@ -16,18 +16,19 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldRecolorYellowToHotPink() public void ImageShouldRecolorYellowToHotPink()
{ {
string path = CreateOutputDirectory("Drawing", "RecolorImage"); string path = this.CreateOutputDirectory("Drawing", "RecolorImage");
var brush = new RecolorBrush(Color.Yellow, Color.HotPink, 0.2f); RecolorBrush brush = new RecolorBrush(Color.Yellow, Color.HotPink, 0.2f);
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Fill(brush) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
.Save(output); {
image.Fill(brush)
.Save(output);
}
} }
} }
} }
@ -35,19 +36,20 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldRecolorYellowToHotPinkInARectangle() public void ImageShouldRecolorYellowToHotPinkInARectangle()
{ {
string path = CreateOutputDirectory("Drawing", "RecolorImage"); string path = this.CreateOutputDirectory("Drawing", "RecolorImage");
var brush = new RecolorBrush(Color.Yellow, Color.HotPink, 0.2f); RecolorBrush brush = new RecolorBrush(Color.Yellow, Color.HotPink, 0.2f);
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/Shaped_{file.FileName}"))
{ {
var imageHeight = image.Height; using (FileStream output = File.OpenWrite($"{path}/Shaped_{file.FileName}"))
image.Fill(brush, new Rectangle(0, imageHeight/2 - imageHeight/4, image.Width, imageHeight/2)) {
.Save(output); int imageHeight = image.Height;
image.Fill(brush, new Rectangle(0, imageHeight/2 - imageHeight/4, image.Width, imageHeight/2))
.Save(output);
}
} }
} }
} }

102
tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs

@ -5,11 +5,8 @@
namespace ImageSharp.Tests.Drawing namespace ImageSharp.Tests.Drawing
{ {
using Drawing;
using ImageSharp.Drawing;
using ImageSharp.Drawing.Shapes; using ImageSharp.Drawing.Shapes;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using Xunit; using Xunit;
@ -19,83 +16,84 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygon() public void ImageShouldBeOverlayedByFilledPolygon()
{ {
string path = CreateOutputDirectory("Drawing", "FilledBezier"); string path = this.CreateOutputDirectory("Drawing", "FilledBezier");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 400), new Vector2(10, 400),
new Vector2(30, 10), new Vector2(30, 10),
new Vector2(240, 30), new Vector2(240, 30),
new Vector2(300, 400) new Vector2(300, 400)
}; };
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.Fill(Color.HotPink,new BezierPolygon(simplePath)) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(Color.HotPink,new BezierPolygon(simplePath))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
//top of curve //top of curve
Assert.Equal(Color.HotPink, sourcePixels[138, 116]); Assert.Equal(Color.HotPink, sourcePixels[138, 116]);
//start points //start points
Assert.Equal(Color.HotPink, sourcePixels[10, 400]); Assert.Equal(Color.HotPink, sourcePixels[10, 400]);
Assert.Equal(Color.HotPink, sourcePixels[300, 400]); Assert.Equal(Color.HotPink, sourcePixels[300, 400]);
//curve points should not be never be set //curve points should not be never be set
Assert.Equal(Color.Blue, sourcePixels[30, 10]); Assert.Equal(Color.Blue, sourcePixels[30, 10]);
Assert.Equal(Color.Blue, sourcePixels[240, 30]); Assert.Equal(Color.Blue, sourcePixels[240, 30]);
// inside shape should not be empty // inside shape should not be empty
Assert.Equal(Color.HotPink, sourcePixels[200, 250]); Assert.Equal(Color.HotPink, sourcePixels[200, 250]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygonOpacity() public void ImageShouldBeOverlayedByFilledPolygonOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "FilledBezier"); string path = this.CreateOutputDirectory("Drawing", "FilledBezier");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 400), new Vector2(10, 400),
new Vector2(30, 10), new Vector2(30, 10),
new Vector2(240, 30), new Vector2(240, 30),
new Vector2(300, 400) new Vector2(300, 400)
}; };
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.Fill(color, new BezierPolygon(simplePath)) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(color, new BezierPolygon(simplePath))
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
//top of curve //top of curve
Assert.Equal(mergedColor, sourcePixels[138, 116]); Assert.Equal(mergedColor, sourcePixels[138, 116]);
//start points //start points
Assert.Equal(mergedColor, sourcePixels[10, 400]); Assert.Equal(mergedColor, sourcePixels[10, 400]);
Assert.Equal(mergedColor, sourcePixels[300, 400]); Assert.Equal(mergedColor, sourcePixels[300, 400]);
//curve points should not be never be set //curve points should not be never be set
Assert.Equal(Color.Blue, sourcePixels[30, 10]); Assert.Equal(Color.Blue, sourcePixels[30, 10]);
Assert.Equal(Color.Blue, sourcePixels[240, 30]); Assert.Equal(Color.Blue, sourcePixels[240, 30]);
// inside shape should not be empty // inside shape should not be empty
Assert.Equal(mergedColor, sourcePixels[200, 250]); Assert.Equal(mergedColor, sourcePixels[200, 250]);
}
} }
} }
} }
} }

138
tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs

@ -5,12 +5,9 @@
namespace ImageSharp.Tests.Drawing namespace ImageSharp.Tests.Drawing
{ {
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using Xunit; using Xunit;
using Drawing;
using ImageSharp.Drawing;
using System.Numerics; using System.Numerics;
using ImageSharp.Drawing.Shapes; using ImageSharp.Drawing.Shapes;
@ -19,41 +16,42 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByPolygonOutline() public void ImageShouldBeOverlayedByPolygonOutline()
{ {
string path = CreateOutputDirectory("Drawing", "ComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "ComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(93, 85), new Vector2(93, 85),
new Vector2(65, 137)); new Vector2(65, 137));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.Fill(Color.HotPink, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(Color.HotPink, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[11, 11]); Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]); Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.HotPink, sourcePixels[35, 100]); Assert.Equal(Color.HotPink, sourcePixels[35, 100]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
}
} }
} }
@ -61,87 +59,89 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedPolygonOutlineWithOverlap() public void ImageShouldBeOverlayedPolygonOutlineWithOverlap()
{ {
string path = CreateOutputDirectory("Drawing", "ComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "ComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(130, 40), new Vector2(130, 40),
new Vector2(65, 137)); new Vector2(65, 137));
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/SimpleOverlapping.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/SimpleOverlapping.png"))
.BackgroundColor(Color.Blue) {
.Fill(Color.HotPink, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(Color.HotPink, new ComplexPolygon(simplePath, hole1))
.Save(output);
using (var sourcePixels = image.Lock()) }
{
Assert.Equal(Color.HotPink, sourcePixels[11, 11]); using (PixelAccessor<Color> sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]); Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.HotPink, sourcePixels[35, 100]); Assert.Equal(Color.HotPink, sourcePixels[35, 100]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() public void ImageShouldBeOverlayedPolygonOutlineWithOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "ComplexPolygon"); string path = this.CreateOutputDirectory("Drawing", "ComplexPolygon");
var simplePath = new LinearPolygon( LinearPolygon simplePath = new LinearPolygon(
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300)); new Vector2(50, 300));
var hole1 = new LinearPolygon( LinearPolygon hole1 = new LinearPolygon(
new Vector2(37, 85), new Vector2(37, 85),
new Vector2(93, 85), new Vector2(93, 85),
new Vector2(65, 137)); new Vector2(65, 137));
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Opacity.png")) using (Image image = new Image(500, 500))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.Fill(color, new ComplexPolygon(simplePath, hole1)) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(color, new ComplexPolygon(simplePath, hole1))
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[11, 11]); Assert.Equal(mergedColor, sourcePixels[11, 11]);
Assert.Equal(mergedColor, sourcePixels[200, 150]); Assert.Equal(mergedColor, sourcePixels[200, 150]);
Assert.Equal(mergedColor, sourcePixels[50, 50]); Assert.Equal(mergedColor, sourcePixels[50, 50]);
Assert.Equal(mergedColor, sourcePixels[35, 100]); Assert.Equal(mergedColor, sourcePixels[35, 100]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
//inside hole //inside hole
Assert.Equal(Color.Blue, sourcePixels[57, 99]); Assert.Equal(Color.Blue, sourcePixels[57, 99]);
}
} }
} }
} }
} }

156
tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs

@ -5,10 +5,8 @@
namespace ImageSharp.Tests.Drawing namespace ImageSharp.Tests.Drawing
{ {
using Drawing;
using ImageSharp.Drawing; using ImageSharp.Drawing;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using Xunit; using Xunit;
@ -19,155 +17,153 @@ namespace ImageSharp.Tests.Drawing
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygon() public void ImageShouldBeOverlayedByFilledPolygon()
{ {
string path = CreateOutputDirectory("Drawing", "FilledPolygons"); string path = this.CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}; };
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Simple.png")) using (Image image = new Image(500, 500))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
.BackgroundColor(Color.Blue) {
.FillPolygon(Color.HotPink, simplePath, new GraphicsOptions(true)) image
.Save(output); .BackgroundColor(Color.Blue)
} .FillPolygon(Color.HotPink, simplePath, new GraphicsOptions(true))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[11, 11]); Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]); Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygon_NoAntialias() public void ImageShouldBeOverlayedByFilledPolygonNoAntialias()
{ {
string path = CreateOutputDirectory("Drawing", "FilledPolygons"); string path = this.CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}; };
var image = new Image(500, 500);
using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Simple_NoAntialias.png")) using (FileStream output = File.OpenWrite($"{path}/Simple_NoAntialias.png"))
{ {
image image
.BackgroundColor(Color.Blue) .BackgroundColor(Color.Blue)
.FillPolygon(Color.HotPink, simplePath, new GraphicsOptions(false)) .FillPolygon(Color.HotPink, simplePath, new GraphicsOptions(false))
.Save(output); .Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[11, 11]); Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]); Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]); Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygon_Image() public void ImageShouldBeOverlayedByFilledPolygonImage()
{ {
string path = CreateOutputDirectory("Drawing", "FilledPolygons"); string path = this.CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}; };
var brush = new ImageBrush(TestFile.Create(TestImages.Bmp.Car).CreateImage()); using (Image brushImage = TestFile.Create(TestImages.Bmp.Car).CreateImage())
var image = new Image(500, 500); using (Image image = new Image(500, 500))
using (FileStream output = File.OpenWrite($"{path}/Image.png")) using (FileStream output = File.OpenWrite($"{path}/Image.png"))
{ {
ImageBrush brush = new ImageBrush(brushImage);
image image
.BackgroundColor(Color.Blue) .BackgroundColor(Color.Blue)
.FillPolygon(brush, simplePath) .FillPolygon(brush, simplePath)
.Save(output); .Save(output);
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledPolygonOpacity() public void ImageShouldBeOverlayedByFilledPolygonOpacity()
{ {
string path = CreateOutputDirectory("Drawing", "FilledPolygons"); string path = this.CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] { Vector2[] simplePath = new[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
}; };
var color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150); Color color = new Color(Color.HotPink.R, Color.HotPink.G, Color.HotPink.B, 150);
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Opacity.png")) using (Image image = new Image(500, 500))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
.BackgroundColor(Color.Blue) {
.FillPolygon(color, simplePath) image
.Save(output); .BackgroundColor(Color.Blue)
} .FillPolygon(color, simplePath)
.Save(output);
}
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
var mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f)); Color mergedColor = new Color(Vector4.Lerp(Color.Blue.ToVector4(), Color.HotPink.ToVector4(), 150f / 255f));
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(mergedColor, sourcePixels[11, 11]); Assert.Equal(mergedColor, sourcePixels[11, 11]);
Assert.Equal(mergedColor, sourcePixels[200, 150]); Assert.Equal(mergedColor, sourcePixels[200, 150]);
Assert.Equal(mergedColor, sourcePixels[50, 50]); Assert.Equal(mergedColor, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
[Fact] [Fact]
public void ImageShouldBeOverlayedByFilledRectangle() public void ImageShouldBeOverlayedByFilledRectangle()
{ {
string path = CreateOutputDirectory("Drawing", "FilledPolygons"); string path = this.CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] { using (Image image = new Image(500, 500))
new Vector2(10, 10),
new Vector2(200, 10),
new Vector2(200, 150),
new Vector2(10, 150)
};
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
{ {
image using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
.BackgroundColor(Color.Blue) {
.Fill(Color.HotPink, new ImageSharp.Drawing.Shapes.RectangularPolygon(new Rectangle(10,10, 190, 140))) image
.Save(output); .BackgroundColor(Color.Blue)
} .Fill(Color.HotPink, new ImageSharp.Drawing.Shapes.RectangularPolygon(new Rectangle(10, 10, 190, 140)))
.Save(output);
}
using (var sourcePixels = image.Lock()) using (PixelAccessor<Color> sourcePixels = image.Lock())
{ {
Assert.Equal(Color.HotPink, sourcePixels[11, 11]); Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[198, 10]); Assert.Equal(Color.HotPink, sourcePixels[198, 10]);
Assert.Equal(Color.HotPink, sourcePixels[10, 50]); Assert.Equal(Color.HotPink, sourcePixels[10, 50]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]); Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]); Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
} }
} }
} }

15
tests/ImageSharp.Tests/Formats/Bmp/BitmapTests.cs

@ -9,8 +9,6 @@ namespace ImageSharp.Tests
{ {
using System.IO; using System.IO;
using Formats;
using Xunit; using Xunit;
public class BitmapTests : FileTestBase public class BitmapTests : FileTestBase
@ -23,19 +21,20 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("BitsPerPixel")] [MemberData(nameof(BitsPerPixel))]
public void BitmapCanEncodeDifferentBitRates(BmpBitsPerPixel bitsPerPixel) public void BitmapCanEncodeDifferentBitRates(BmpBitsPerPixel bitsPerPixel)
{ {
string path = CreateOutputDirectory("Bmp"); string path = this.CreateOutputDirectory("Bmp");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileNameWithoutExtension(bitsPerPixel); string filename = file.GetFileNameWithoutExtension(bitsPerPixel);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}.bmp"))
{ {
image.Save(output, new BmpEncoder { BitsPerPixel = bitsPerPixel }); using (FileStream output = File.OpenWrite($"{path}/{filename}.bmp"))
{
image.Save(output, new BmpEncoder { BitsPerPixel = bitsPerPixel });
}
} }
} }
} }

101
tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs

@ -16,17 +16,18 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ResolutionShouldChange() public void ResolutionShouldChange()
{ {
string path = CreateOutputDirectory("Resolution"); string path = this.CreateOutputDirectory("Resolution");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.VerticalResolution = 150; using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
image.HorizontalResolution = 150; {
image.Save(output); image.VerticalResolution = 150;
image.HorizontalResolution = 150;
image.Save(output);
}
} }
} }
} }
@ -34,45 +35,31 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageCanEncodeToString() public void ImageCanEncodeToString()
{ {
string path = CreateOutputDirectory("ToString"); string path = this.CreateOutputDirectory("ToString");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
{
string filename = path + "/" + file.FileNameWithoutExtension + ".txt"; string filename = path + "/" + file.FileNameWithoutExtension + ".txt";
File.WriteAllText(filename, image.ToBase64String()); File.WriteAllText(filename, image.ToBase64String());
}
} }
} }
[Fact] [Fact]
public void DecodeThenEncodeImageFromStreamShouldSucceed() public void DecodeThenEncodeImageFromStreamShouldSucceed()
{ {
string path = CreateOutputDirectory("Encode"); string path = this.CreateOutputDirectory("Encode");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
//Image<Bgr565> image = file.CreateImage().To<Bgr565>();
//Image<Bgra4444> image = file.CreateImage().To<Bgra4444>();
//Image<Bgra5551> image = file.CreateImage().To<Bgra5551>();
//Image<Byte4> image = file.CreateImage().To<Byte4>();
//Image<HalfSingle> image = file.CreateImage().To<HalfSingle>();
//Image<HalfVector2> image = file.CreateImage().To<HalfVector2>();
//Image<HalfVector4> image = file.CreateImage().To<HalfVector4>();
//Image<Rg32> image = file.CreateImage().To<Rg32>();
//Image<Rgba1010102> image = file.CreateImage().To<Rgba1010102>();
//Image<Rgba64> image = file.CreateImage().To<Rgba64>();
//Image<NormalizedByte2> image = file.CreateImage().To<NormalizedByte2>();
//Image<NormalizedByte4> image = file.CreateImage().To<NormalizedByte4>();
//Image<NormalizedShort2> image = file.CreateImage().To<NormalizedShort2>();
//Image<NormalizedShort4> image = file.CreateImage().To<NormalizedShort4>();
//Image<Short2> image = file.CreateImage().To<Short2>();
//Image<Short4> image = file.CreateImage().To<Short4>();
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Save(output); using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{
image.Save(output);
}
} }
} }
} }
@ -80,35 +67,35 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void QuantizeImageShouldPreserveMaximumColorPrecision() public void QuantizeImageShouldPreserveMaximumColorPrecision()
{ {
string path = CreateOutputDirectory("Quantize"); string path = this.CreateOutputDirectory("Quantize");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
// Copy the original pixels to save decoding time.
Color[] pixels = new Color[image.Width * image.Height];
Array.Copy(image.Pixels, pixels, image.Pixels.Length);
using (FileStream output = File.OpenWrite($"{path}/Octree-{file.FileName}"))
{ {
image.Quantize(Quantization.Octree) Color[] pixels = new Color[image.Width * image.Height];
.Save(output, image.CurrentImageFormat); Array.Copy(image.Pixels, pixels, image.Width * image.Height);
} using (FileStream output = File.OpenWrite($"{path}/Octree-{file.FileName}"))
{
image.Quantize(Quantization.Octree)
.Save(output, image.CurrentImageFormat);
image.SetPixels(image.Width, image.Height, pixels); }
using (FileStream output = File.OpenWrite($"{path}/Wu-{file.FileName}"))
{
image.Quantize(Quantization.Wu)
.Save(output, image.CurrentImageFormat);
}
image.SetPixels(image.Width, image.Height, pixels); image.SetPixels(image.Width, image.Height, pixels);
using (FileStream output = File.OpenWrite($"{path}/Palette-{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/Wu-{file.FileName}"))
{ {
image.Quantize(Quantization.Palette) image.Quantize(Quantization.Wu)
.Save(output, image.CurrentImageFormat); .Save(output, image.CurrentImageFormat);
}
image.SetPixels(image.Width, image.Height, pixels);
using (FileStream output = File.OpenWrite($"{path}/Palette-{file.FileName}"))
{
image.Quantize(Quantization.Palette)
.Save(output, image.CurrentImageFormat);
}
} }
} }
} }
@ -116,7 +103,7 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageCanConvertFormat() public void ImageCanConvertFormat()
{ {
string path = CreateOutputDirectory("Format"); string path = this.CreateOutputDirectory("Format");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
@ -147,7 +134,7 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldPreservePixelByteOrderWhenSerialized() public void ImageShouldPreservePixelByteOrderWhenSerialized()
{ {
string path = CreateOutputDirectory("Serialized"); string path = this.CreateOutputDirectory("Serialized");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {

16
tests/ImageSharp.Tests/Formats/Jpg/BadEofJpegTests.cs

@ -31,9 +31,11 @@ namespace ImageSharp.Tests
public void LoadBaselineImage<TColor>(TestImageProvider<TColor> provider) public void LoadBaselineImage<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
var image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
Assert.NotNull(image); {
provider.Utility.SaveTestOutputFile(image, "bmp"); Assert.NotNull(image);
provider.Utility.SaveTestOutputFile(image, "bmp");
}
} }
[Theory] // TODO: #18 [Theory] // TODO: #18
@ -41,9 +43,11 @@ namespace ImageSharp.Tests
public void LoadProgressiveImage<TColor>(TestImageProvider<TColor> provider) public void LoadProgressiveImage<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
var image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
Assert.NotNull(image); {
provider.Utility.SaveTestOutputFile(image, "bmp"); Assert.NotNull(image);
provider.Utility.SaveTestOutputFile(image, "bmp");
}
} }
} }
} }

61
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -29,19 +29,21 @@ namespace ImageSharp.Tests
public void OpenBaselineJpeg_SaveBmp<TColor>(TestImageProvider<TColor> provider) public void OpenBaselineJpeg_SaveBmp<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
{
provider.Utility.SaveTestOutputFile(image, "bmp"); provider.Utility.SaveTestOutputFile(image, "bmp");
}
} }
[Theory] [Theory]
[WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Color | PixelTypes.StandardImageClass | PixelTypes.Argb)] [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Color | PixelTypes.StandardImageClass | PixelTypes.Argb)]
public void OpenProgressiveJpeg_SaveBmp<TColor>(TestImageProvider<TColor> provider) public void OpenProgressiveJpeg_SaveBmp<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
{
provider.Utility.SaveTestOutputFile(image, "bmp"); provider.Utility.SaveTestOutputFile(image, "bmp");
}
} }
[Theory] [Theory]
@ -53,17 +55,19 @@ namespace ImageSharp.Tests
public void DecodeGenerated_SaveBmp<TColor>( public void DecodeGenerated_SaveBmp<TColor>(
TestImageProvider<TColor> provider, TestImageProvider<TColor> provider,
JpegSubsample subsample, JpegSubsample subsample,
int quality) int quality)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage(); byte[] data;
using (Image<TColor> image = provider.GetImage())
JpegEncoder encoder = new JpegEncoder() { Subsample = subsample, Quality = quality };
byte[] data = new byte[65536];
using (MemoryStream ms = new MemoryStream(data))
{ {
image.Save(ms, encoder); JpegEncoder encoder = new JpegEncoder() { Subsample = subsample, Quality = quality };
data = new byte[65536];
using (MemoryStream ms = new MemoryStream(data))
{
image.Save(ms, encoder);
}
} }
// TODO: Automatic image comparers could help here a lot :P // TODO: Automatic image comparers could help here a lot :P
@ -75,23 +79,24 @@ namespace ImageSharp.Tests
[Theory] [Theory]
[WithSolidFilledImages(42, 88, 255, 0, 0, PixelTypes.StandardImageClass)] [WithSolidFilledImages(42, 88, 255, 0, 0, PixelTypes.StandardImageClass)]
public void DecodeGenerated_MetadataOnly<TColor>( public void DecodeGenerated_MetadataOnly<TColor>(
TestImageProvider<TColor> provider) TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
using (MemoryStream ms = new MemoryStream())
{ {
image.Save(ms, new JpegEncoder()); using (MemoryStream ms = new MemoryStream())
ms.Seek(0, SeekOrigin.Begin);
Image<TColor> mirror = provider.Factory.CreateImage(1, 1);
using (JpegDecoderCore decoder = new JpegDecoderCore())
{ {
decoder.Decode(mirror, ms, true); image.Save(ms, new JpegEncoder());
ms.Seek(0, SeekOrigin.Begin);
Assert.Equal(decoder.ImageWidth, image.Width);
Assert.Equal(decoder.ImageHeight, image.Height); Image<TColor> mirror = provider.Factory.CreateImage(1, 1);
using (JpegDecoderCore decoder = new JpegDecoderCore())
{
decoder.Decode(mirror, ms, true);
Assert.Equal(decoder.ImageWidth, image.Width);
Assert.Equal(decoder.ImageHeight, image.Height);
}
} }
} }
} }

44
tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs

@ -34,19 +34,16 @@ namespace ImageSharp.Tests
public void LoadResizeSave<TColor>(TestImageProvider<TColor> provider, int quality, JpegSubsample subsample) public void LoadResizeSave<TColor>(TestImageProvider<TColor> provider, int quality, JpegSubsample subsample)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage() using (Image<TColor> image = provider.GetImage().Resize(new ResizeOptions { Size = new Size(150, 100), Mode = ResizeMode.Max }))
.Resize(new ResizeOptions {
{ image.Quality = quality;
Size = new Size(150, 100), image.ExifProfile = null; // Reduce the size of the file
Mode = ResizeMode.Max JpegEncoder encoder = new JpegEncoder { Subsample = subsample, Quality = quality };
});
image.Quality = quality;
image.ExifProfile = null; // Reduce the size of the file
JpegEncoder encoder = new JpegEncoder { Subsample = subsample, Quality = quality };
provider.Utility.TestName += $"{subsample}_Q{quality}"; provider.Utility.TestName += $"{subsample}_Q{quality}";
provider.Utility.SaveTestOutputFile(image, "png"); provider.Utility.SaveTestOutputFile(image, "png");
provider.Utility.SaveTestOutputFile(image, "jpg", encoder); provider.Utility.SaveTestOutputFile(image, "jpg", encoder);
}
} }
[Theory] [Theory]
@ -55,20 +52,21 @@ namespace ImageSharp.Tests
public void OpenBmp_SaveJpeg<TColor>(TestImageProvider<TColor> provider, JpegSubsample subSample, int quality) public void OpenBmp_SaveJpeg<TColor>(TestImageProvider<TColor> provider, JpegSubsample subSample, int quality)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = provider.GetImage(); using (Image<TColor> image = provider.GetImage())
ImagingTestCaseUtility utility = provider.Utility;
utility.TestName += "_" + subSample + "_Q" + quality;
using (var outputStream = File.OpenWrite(utility.GetTestOutputFileName("jpg")))
{ {
var encoder = new JpegEncoder() ImagingTestCaseUtility utility = provider.Utility;
utility.TestName += "_" + subSample + "_Q" + quality;
using (FileStream outputStream = File.OpenWrite(utility.GetTestOutputFileName("jpg")))
{ {
Subsample = subSample, JpegEncoder encoder = new JpegEncoder()
Quality = quality {
}; Subsample = subSample,
Quality = quality
};
image.Save(outputStream, encoder); image.Save(outputStream, encoder);
}
} }
} }
} }

85
tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs

@ -19,7 +19,6 @@ namespace ImageSharp.Tests
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = factory.CreateImage(10, 10); Image<TColor> image = factory.CreateImage(10, 10);
using (PixelAccessor<TColor> pixels = image.Lock()) using (PixelAccessor<TColor> pixels = image.Lock())
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
@ -35,6 +34,7 @@ namespace ImageSharp.Tests
} }
} }
} }
return image; return image;
} }
@ -43,24 +43,21 @@ namespace ImageSharp.Tests
public void CopyStretchedRGBTo_FromOrigo<TColor>(TestImageProvider<TColor> provider) public void CopyStretchedRGBTo_FromOrigo<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> src = provider.GetImage(); using (Image<TColor> src = provider.GetImage())
using (Image<TColor> dest = provider.Factory.CreateImage(8, 8))
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz); using (PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz))
Image<TColor> dest = provider.Factory.CreateImage(8, 8); using (PixelAccessor<TColor> s = src.Lock())
using (PixelAccessor<TColor> d = dest.Lock())
using (var s = src.Lock())
{ {
using (var d = dest.Lock()) s.CopyRGBBytesStretchedTo(area, 0, 0);
{ d.CopyFrom(area, 0, 0);
s.CopyRGBBytesStretchedTo(area, 0, 0);
d.CopyFrom(area, 0, 0);
Assert.Equal(s[0, 0], d[0, 0]); Assert.Equal(s[0, 0], d[0, 0]);
Assert.Equal(s[7, 0], d[7, 0]); Assert.Equal(s[7, 0], d[7, 0]);
Assert.Equal(s[0, 7], d[0, 7]); Assert.Equal(s[0, 7], d[0, 7]);
Assert.Equal(s[7, 7], d[7, 7]); Assert.Equal(s[7, 7], d[7, 7]);
}
} }
} }
[Theory] [Theory]
@ -68,45 +65,41 @@ namespace ImageSharp.Tests
public void CopyStretchedRGBTo_WithOffset<TColor>(TestImageProvider<TColor> provider) public void CopyStretchedRGBTo_WithOffset<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> src = provider.GetImage(); using (Image<TColor> src = provider.GetImage())
using (PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz))
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz); using (Image<TColor> dest = provider.Factory.CreateImage(8, 8))
Image<TColor> dest = provider.Factory.CreateImage(8, 8);
using (PixelAccessor<TColor> s = src.Lock()) using (PixelAccessor<TColor> s = src.Lock())
using (PixelAccessor<TColor> d = dest.Lock())
{ {
using (var d = dest.Lock()) s.CopyRGBBytesStretchedTo(area, 7, 6);
{ d.CopyFrom(area, 0, 0);
s.CopyRGBBytesStretchedTo(area, 7, 6);
d.CopyFrom(area, 0, 0);
Assert.Equal(s[6, 7], d[0, 0]); Assert.Equal(s[6, 7], d[0, 0]);
Assert.Equal(s[6, 8], d[0, 1]); Assert.Equal(s[6, 8], d[0, 1]);
Assert.Equal(s[7, 8], d[1, 1]); Assert.Equal(s[7, 8], d[1, 1]);
Assert.Equal(s[6, 9], d[0, 2]); Assert.Equal(s[6, 9], d[0, 2]);
Assert.Equal(s[6, 9], d[0, 3]); Assert.Equal(s[6, 9], d[0, 3]);
Assert.Equal(s[6, 9], d[0, 7]); Assert.Equal(s[6, 9], d[0, 7]);
Assert.Equal(s[7, 9], d[1, 2]); Assert.Equal(s[7, 9], d[1, 2]);
Assert.Equal(s[7, 9], d[1, 3]); Assert.Equal(s[7, 9], d[1, 3]);
Assert.Equal(s[7, 9], d[1, 7]); Assert.Equal(s[7, 9], d[1, 7]);
Assert.Equal(s[9, 9], d[3, 2]); Assert.Equal(s[9, 9], d[3, 2]);
Assert.Equal(s[9, 9], d[3, 3]); Assert.Equal(s[9, 9], d[3, 3]);
Assert.Equal(s[9, 9], d[3, 7]); Assert.Equal(s[9, 9], d[3, 7]);
Assert.Equal(s[9, 7], d[3, 0]); Assert.Equal(s[9, 7], d[3, 0]);
Assert.Equal(s[9, 7], d[4, 0]); Assert.Equal(s[9, 7], d[4, 0]);
Assert.Equal(s[9, 7], d[7, 0]); Assert.Equal(s[9, 7], d[7, 0]);
Assert.Equal(s[9, 9], d[3, 2]); Assert.Equal(s[9, 9], d[3, 2]);
Assert.Equal(s[9, 9], d[4, 2]); Assert.Equal(s[9, 9], d[4, 2]);
Assert.Equal(s[9, 9], d[7, 2]); Assert.Equal(s[9, 9], d[7, 2]);
Assert.Equal(s[9, 9], d[4, 3]); Assert.Equal(s[9, 9], d[4, 3]);
Assert.Equal(s[9, 9], d[7, 7]); Assert.Equal(s[9, 9], d[7, 7]);
}
} }
} }
} }

4
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.cs

@ -6,8 +6,6 @@
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace ImageSharp.Tests.Formats.Jpg namespace ImageSharp.Tests.Formats.Jpg
{ {
using System.Numerics;
using ImageSharp.Formats;
using ImageSharp.Formats.Jpg; using ImageSharp.Formats.Jpg;
using Xunit; using Xunit;
@ -97,7 +95,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual, new ApproximateFloatComparer(2f)); Assert.Equal(expected, actual, new ApproximateFloatComparer(2f));
} }
} }
[Theory] [Theory]
[InlineData(42)] [InlineData(42)]
[InlineData(1)] [InlineData(1)]

20
tests/ImageSharp.Tests/Formats/Png/PngTests.cs

@ -23,12 +23,13 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{ {
image.Quality = 256; using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
image.Save(output, new PngFormat()); {
image.Quality = 256;
image.Save(output, new PngFormat());
}
} }
} }
} }
@ -42,11 +43,12 @@ namespace ImageSharp.Tests
Files, Files,
file => file =>
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{ {
image.SaveAsPng(output); using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{
image.SaveAsPng(output);
}
} }
}); });
} }

9
tests/ImageSharp.Tests/Image/ImageTests.cs

@ -23,10 +23,11 @@ namespace ImageSharp.Tests
}); });
TestFile file = TestFile.Create(TestImages.Bmp.Car); TestFile file = TestFile.Create(TestImages.Bmp.Car);
Image image = new Image(file.Bytes); using (Image image = new Image(file.Bytes))
{
Assert.Equal(600, image.Width); Assert.Equal(600, image.Width);
Assert.Equal(450, image.Height); Assert.Equal(450, image.Height);
}
} }
} }
} }

118
tests/ImageSharp.Tests/Image/PixelAccessorTests.cs

@ -19,8 +19,7 @@ namespace ImageSharp.Tests
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
Image<TColor> image = factory.CreateImage(10, 10); Image<TColor> image = factory.CreateImage(10, 10);
using (PixelAccessor<TColor> pixels = image.Lock())
using (var pixels = image.Lock())
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
@ -47,31 +46,33 @@ namespace ImageSharp.Tests
public void CopyTo_Then_CopyFrom_OnFullImageRect<TColor>(TestImageProvider<TColor> provider, ComponentOrder order) public void CopyTo_Then_CopyFrom_OnFullImageRect<TColor>(TestImageProvider<TColor> provider, ComponentOrder order)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
var src = provider.GetImage(); using (Image<TColor> src = provider.GetImage())
var dest = new Image<TColor>(src.Width, src.Height);
using (PixelArea<TColor> area = new PixelArea<TColor>(src.Width, src.Height, order))
{ {
using (var srcPixels = src.Lock()) using (Image<TColor> dest = new Image<TColor>(src.Width, src.Height))
{ {
srcPixels.CopyTo(area, 0, 0); using (PixelArea<TColor> area = new PixelArea<TColor>(src.Width, src.Height, order))
} {
using (PixelAccessor<TColor> srcPixels = src.Lock())
{
srcPixels.CopyTo(area, 0, 0);
}
using (PixelAccessor<TColor> destPixels = dest.Lock())
{
destPixels.CopyFrom(area, 0, 0);
}
}
using (var destPixels = dest.Lock()) Assert.True(src.IsEquivalentTo(dest, false));
{
destPixels.CopyFrom(area, 0, 0);
} }
} }
Assert.True(src.IsEquivalentTo(dest, false));
} }
// TODO: Need a processor in the library with this signature // TODO: Need a processor in the library with this signature
private static void Fill<TColor>(Image<TColor> image, Rectangle region, TColor color) private static void Fill<TColor>(Image<TColor> image, Rectangle region, TColor color)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
using (var pixels = image.Lock()) using (PixelAccessor<TColor> pixels = image.Lock())
{ {
for (int y = region.Top; y < region.Bottom; y++) for (int y = region.Top; y < region.Bottom; y++)
{ {
@ -88,87 +89,114 @@ namespace ImageSharp.Tests
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyx)] [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyx)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyzw)] [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyzw)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyxw)] [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyxw)]
public void CopyTo_Then_CopyFrom_WithOffset<TColor>(TestImageProvider<TColor> provider, ComponentOrder order) public void CopyToThenCopyFromWithOffset<TColor>(TestImageProvider<TColor> provider, ComponentOrder order)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
var srcImage = provider.GetImage(); using (Image<TColor> destImage = new Image<TColor>(8, 8))
var color = default(TColor);
color.PackFromBytes(255, 0, 0, 255);
Fill(srcImage, new Rectangle(4, 4, 8, 8), color);
var destImage = new Image<TColor>(8, 8);
using (var srcPixels = srcImage.Lock())
{ {
using (var area = new PixelArea<TColor>(8, 8, order)) TColor color;
using (Image<TColor> srcImage = provider.GetImage())
{ {
srcPixels.CopyTo(area, 4, 4); color = default(TColor);
color.PackFromBytes(255, 0, 0, 255);
using (var destPixels = destImage.Lock()) Fill(srcImage, new Rectangle(4, 4, 8, 8), color);
using (PixelAccessor<TColor> srcPixels = srcImage.Lock())
{ {
destPixels.CopyFrom(area, 0, 0); using (PixelArea<TColor> area = new PixelArea<TColor>(8, 8, order))
{
srcPixels.CopyTo(area, 4, 4);
using (PixelAccessor<TColor> destPixels = destImage.Lock())
{
destPixels.CopyFrom(area, 0, 0);
}
}
} }
} }
}
provider.Utility.SourceFileOrDescription = order.ToString();
provider.Utility.SaveTestOutputFile(destImage, "bmp");
var expectedImage = new Image<TColor>(8, 8).Fill(color); provider.Utility.SourceFileOrDescription = order.ToString();
provider.Utility.SaveTestOutputFile(destImage, "bmp");
Assert.True(destImage.IsEquivalentTo(expectedImage)); using (Image<TColor> expectedImage = new Image<TColor>(8, 8).Fill(color))
{
Assert.True(destImage.IsEquivalentTo(expectedImage));
}
}
} }
[Fact] [Fact]
public void CopyFromZYX() public void CopyFromZYX()
{ {
CopyFromZYX(new Image(1, 1)); using (Image<Color> image = new Image<Color>(1, 1))
{
CopyFromZYX(image);
}
} }
[Fact] [Fact]
public void CopyFromZYXOptimized() public void CopyFromZYXOptimized()
{ {
CopyFromZYX(new Image(1, 1)); using (Image image = new Image(1, 1))
{
CopyFromZYX(image);
}
} }
[Fact] [Fact]
public void CopyFromZYXW() public void CopyFromZYXW()
{ {
CopyFromZYXW(new Image(1, 1)); using (Image<Color> image = new Image<Color>(1, 1))
{
CopyFromZYXW(image);
}
} }
[Fact] [Fact]
public void CopyFromZYXWOptimized() public void CopyFromZYXWOptimized()
{ {
CopyFromZYXW(new Image(1, 1)); using (Image image = new Image(1, 1))
{
CopyFromZYXW(image);
}
} }
[Fact] [Fact]
public void CopyToZYX() public void CopyToZYX()
{ {
CopyToZYX(new Image(1, 1)); using (Image<Color> image = new Image<Color>(1, 1))
{
CopyToZYX(image);
}
} }
[Fact] [Fact]
public void CopyToZYXOptimized() public void CopyToZYXOptimized()
{ {
CopyToZYX(new Image(1, 1)); using (Image image = new Image(1, 1))
{
CopyToZYX(image);
}
} }
[Fact] [Fact]
public void CopyToZYXW() public void CopyToZYXW()
{ {
CopyToZYXW(new Image(1, 1)); using (Image<Color> image = new Image<Color>(1, 1))
{
CopyToZYXW(image);
}
} }
[Fact] [Fact]
public void CopyToZYXWOptimized() public void CopyToZYXWOptimized()
{ {
CopyToZYXW(new Image(1, 1)); using (Image image = new Image(1, 1))
{
CopyToZYXW(image);
}
} }
private static void CopyFromZYX<TColor>(Image<TColor> image) private static void CopyFromZYX<TColor>(Image<TColor> image)

20
tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs

@ -19,39 +19,35 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("AlphaValues")] [MemberData(nameof(AlphaValues))]
public void ImageShouldApplyAlphaFilter(int value) public void ImageShouldApplyAlphaFilter(int value)
{ {
string path = CreateOutputDirectory("Alpha"); string path = this.CreateOutputDirectory("Alpha");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Alpha(value) image.Alpha(value).Save(output);
.Save(output);
} }
} }
} }
[Theory] [Theory]
[MemberData("AlphaValues")] [MemberData(nameof(AlphaValues))]
public void ImageShouldApplyAlphaFilterInBox(int value) public void ImageShouldApplyAlphaFilterInBox(int value)
{ {
string path = CreateOutputDirectory("Alpha"); string path = this.CreateOutputDirectory("Alpha");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Alpha(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)) image.Alpha(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output);
.Save(output);
} }
} }
} }

19
tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs

@ -26,25 +26,22 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("OrientationValues")] [MemberData(nameof(OrientationValues))]
public void ImageShouldFlip(RotateType rotateType, FlipType flipType, ushort orientation) public void ImageShouldFlip(RotateType rotateType, FlipType flipType, ushort orientation)
{ {
string path = CreateOutputDirectory("AutoOrient"); string path = this.CreateOutputDirectory("AutoOrient");
TestFile file = TestFile.Create(TestImages.Bmp.F); TestFile file = TestFile.Create(TestImages.Bmp.F);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
image.ExifProfile = new ExifProfile();
image.ExifProfile.SetValue(ExifTag.Orientation, orientation);
using (FileStream before = File.OpenWrite($"{path}/before-{file.FileName}"))
{ {
image.ExifProfile = new ExifProfile();
image.ExifProfile.SetValue(ExifTag.Orientation, orientation);
using (FileStream before = File.OpenWrite($"{path}/before-{file.FileName}"))
using (FileStream after = File.OpenWrite($"{path}/after-{file.FileName}")) using (FileStream after = File.OpenWrite($"{path}/after-{file.FileName}"))
{ {
image.RotateFlip(rotateType, flipType) image.RotateFlip(rotateType, flipType).Save(before).AutoOrient().Save(after);
.Save(before)
.AutoOrient()
.Save(after);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyBackgroundColorFilter() public void ImageShouldApplyBackgroundColorFilter()
{ {
string path = CreateOutputDirectory("BackgroundColor"); string path = this.CreateOutputDirectory("BackgroundColor");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.BackgroundColor(Color.HotPink) image.BackgroundColor(Color.HotPink).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/BinaryThreshold.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("BinaryThresholdValues")] [MemberData(nameof(BinaryThresholdValues))]
public void ImageShouldApplyBinaryThresholdFilter(float value) public void ImageShouldApplyBinaryThresholdFilter(float value)
{ {
string path = CreateOutputDirectory("BinaryThreshold"); string path = this.CreateOutputDirectory("BinaryThreshold");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.BinaryThreshold(value) image.BinaryThreshold(value).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyBlackWhiteFilter() public void ImageShouldApplyBlackWhiteFilter()
{ {
string path = CreateOutputDirectory("BlackWhite"); string path = this.CreateOutputDirectory("BlackWhite");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.BlackWhite() image.BlackWhite().Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("BoxBlurValues")] [MemberData(nameof(BoxBlurValues))]
public void ImageShouldApplyBoxBlurFilter(int value) public void ImageShouldApplyBoxBlurFilter(int value)
{ {
string path = CreateOutputDirectory("BoxBlur"); string path = this.CreateOutputDirectory("BoxBlur");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.BoxBlur(value) image.BoxBlur(value).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("BrightnessValues")] [MemberData(nameof(BrightnessValues))]
public void ImageShouldApplyBrightnessFilter(int value) public void ImageShouldApplyBrightnessFilter(int value)
{ {
string path = CreateOutputDirectory("Brightness"); string path = this.CreateOutputDirectory("Brightness");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Brightness(value) image.Brightness(value).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs

@ -26,20 +26,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("ColorBlindnessFilters")] [MemberData(nameof(ColorBlindnessFilters))]
public void ImageShouldApplyColorBlindnessFilter(ColorBlindness colorBlindness) public void ImageShouldApplyColorBlindnessFilter(ColorBlindness colorBlindness)
{ {
string path = CreateOutputDirectory("ColorBlindness"); string path = this.CreateOutputDirectory("ColorBlindness");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(colorBlindness); string filename = file.GetFileName(colorBlindness);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.ColorBlindness(colorBlindness) image.ColorBlindness(colorBlindness).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs

@ -19,19 +19,17 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("ContrastValues")] [MemberData(nameof(ContrastValues))]
public void ImageShouldApplyContrastFilter(int value) public void ImageShouldApplyContrastFilter(int value)
{ {
string path = CreateOutputDirectory("Contrast"); string path = this.CreateOutputDirectory("Contrast");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Contrast(value) image.Contrast(value).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/CropTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyCropSampler() public void ImageShouldApplyCropSampler()
{ {
string path = CreateOutputDirectory("Crop"); string path = this.CreateOutputDirectory("Crop");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Crop(image.Width / 2, image.Height / 2) image.Crop(image.Width / 2, image.Height / 2).Save(output);
.Save(output);
} }
} }
} }

15
tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs

@ -31,32 +31,29 @@ namespace ImageSharp.Tests
[MemberData(nameof(DetectEdgesFilters))] [MemberData(nameof(DetectEdgesFilters))]
public void ImageShouldApplyDetectEdgesFilter(EdgeDetection detector) public void ImageShouldApplyDetectEdgesFilter(EdgeDetection detector)
{ {
string path = CreateOutputDirectory("DetectEdges"); string path = this.CreateOutputDirectory("DetectEdges");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(detector); string filename = file.GetFileName(detector);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.DetectEdges(detector) image.DetectEdges(detector).Save(output);
.Save(output);
} }
} }
} }
[Theory] [Theory]
[MemberData("DetectEdgesFilters")] [MemberData(nameof(DetectEdgesFilters))]
public void ImageShouldApplyDetectEdgesFilterInBox(EdgeDetection detector) public void ImageShouldApplyDetectEdgesFilterInBox(EdgeDetection detector)
{ {
string path = CreateOutputDirectory("DetectEdges"); string path = this.CreateOutputDirectory("DetectEdges");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(detector + "-InBox"); string filename = file.GetFileName(detector + "-InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2))

10
tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("EntropyCropValues")] [MemberData(nameof(EntropyCropValues))]
public void ImageShouldApplyEntropyCropSampler(float value) public void ImageShouldApplyEntropyCropSampler(float value)
{ {
string path = CreateOutputDirectory("EntropyCrop"); string path = this.CreateOutputDirectory("EntropyCrop");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.EntropyCrop(value) image.EntropyCrop(value).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs

@ -20,20 +20,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("FlipValues")] [MemberData(nameof(FlipValues))]
public void ImageShouldFlip(FlipType flipType) public void ImageShouldFlip(FlipType flipType)
{ {
string path = CreateOutputDirectory("Flip"); string path = this.CreateOutputDirectory("Flip");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(flipType); string filename = file.GetFileName(flipType);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Flip(flipType) image.Flip(flipType).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("GaussianBlurValues")] [MemberData(nameof(GaussianBlurValues))]
public void ImageShouldApplyGaussianBlurFilter(int value) public void ImageShouldApplyGaussianBlurFilter(int value)
{ {
string path = CreateOutputDirectory("GaussianBlur"); string path = this.CreateOutputDirectory("GaussianBlur");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.GaussianBlur(value) image.GaussianBlur(value).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("GaussianSharpenValues")] [MemberData(nameof(GaussianSharpenValues))]
public void ImageShouldApplyGaussianSharpenFilter(int value) public void ImageShouldApplyGaussianSharpenFilter(int value)
{ {
string path = CreateOutputDirectory("GaussianSharpen"); string path = this.CreateOutputDirectory("GaussianSharpen");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.GaussianSharpen(value) image.GaussianSharpen(value).Save(output);
.Save(output);
} }
} }
} }

31
tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyGlowFilter() public void ImageShouldApplyGlowFilter()
{ {
string path = CreateOutputDirectory("Glow"); string path = this.CreateOutputDirectory("Glow");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Glow() image.Glow().Save(output);
.Save(output);
} }
} }
} }
@ -31,17 +29,15 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyGlowFilterColor() public void ImageShouldApplyGlowFilterColor()
{ {
string path = CreateOutputDirectory("Glow"); string path = this.CreateOutputDirectory("Glow");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("Color"); string filename = file.GetFileName("Color");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Glow(Color.HotPink) image.Glow(Color.HotPink).Save(output);
.Save(output);
} }
} }
} }
@ -49,17 +45,15 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyGlowFilterRadius() public void ImageShouldApplyGlowFilterRadius()
{ {
string path = CreateOutputDirectory("Glow"); string path = this.CreateOutputDirectory("Glow");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("Radius"); string filename = file.GetFileName("Radius");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Glow(image.Width / 4) image.Glow(image.Width / 4F).Save(output);
.Save(output);
} }
} }
} }
@ -67,17 +61,16 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyGlowFilterInBox() public void ImageShouldApplyGlowFilterInBox()
{ {
string path = CreateOutputDirectory("Glow"); string path = this.CreateOutputDirectory("Glow");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("InBox"); string filename = file.GetFileName("InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Glow(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) image.Glow(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2))
.Save(output); .Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs

@ -20,20 +20,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("GrayscaleValues")] [MemberData(nameof(GrayscaleValues))]
public void ImageShouldApplyGrayscaleFilter(GrayscaleMode value) public void ImageShouldApplyGrayscaleFilter(GrayscaleMode value)
{ {
string path = CreateOutputDirectory("Grayscale"); string path = this.CreateOutputDirectory("Grayscale");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Grayscale(value) image.Grayscale(value).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/HueTest.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("HueValues")] [MemberData(nameof(HueValues))]
public void ImageShouldApplyHueFilter(int value) public void ImageShouldApplyHueFilter(int value)
{ {
string path = CreateOutputDirectory("Hue"); string path = this.CreateOutputDirectory("Hue");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Hue(value) image.Hue(value).Save(output);
.Save(output);
} }
} }
} }

16
tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs

@ -14,15 +14,13 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyInvertFilter() public void ImageShouldApplyInvertFilter()
{ {
string path = CreateOutputDirectory("Invert"); string path = this.CreateOutputDirectory("Invert");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Invert() image.Invert().Save(output);
.Save(output);
} }
} }
} }
@ -30,17 +28,15 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyInvertFilterInBox() public void ImageShouldApplyInvertFilterInBox()
{ {
string path = CreateOutputDirectory("Invert"); string path = this.CreateOutputDirectory("Invert");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("InBox"); string filename = file.GetFileName("InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Invert(new Rectangle(10, 10, image.Width / 2, image.Height / 2)) image.Invert(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyKodachromeFilter() public void ImageShouldApplyKodachromeFilter()
{ {
string path = CreateOutputDirectory("Kodachrome"); string path = this.CreateOutputDirectory("Kodachrome");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Kodachrome() image.Kodachrome().Save(output);
.Save(output);
} }
} }
} }

15
tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyLomographFilter() public void ImageShouldApplyLomographFilter()
{ {
string path = CreateOutputDirectory("Lomograph"); string path = this.CreateOutputDirectory("Lomograph");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Lomograph() image.Lomograph().Save(output);
.Save(output);
} }
} }
} }
@ -31,17 +29,16 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyLomographFilterInBox() public void ImageShouldApplyLomographFilterInBox()
{ {
string path = CreateOutputDirectory("Lomograph"); string path = this.CreateOutputDirectory("Lomograph");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("InBox"); string filename = file.GetFileName("InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Lomograph(new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)) image.Lomograph(new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2))
.Save(output); .Save(output);
} }
} }
} }

21
tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs

@ -23,19 +23,17 @@ namespace ImageSharp.Tests
[MemberData(nameof(OilPaintValues))] [MemberData(nameof(OilPaintValues))]
public void ImageShouldApplyOilPaintFilter(Tuple<int, int> value) public void ImageShouldApplyOilPaintFilter(Tuple<int, int> value)
{ {
string path = CreateOutputDirectory("OilPaint"); string path = this.CreateOutputDirectory("OilPaint");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
if (image.Width > value.Item2 && image.Height > value.Item2) if (image.Width > value.Item2 && image.Height > value.Item2)
{ {
image.OilPaint(value.Item1, value.Item2) image.OilPaint(value.Item1, value.Item2).Save(output);
.Save(output);
} }
} }
} }
@ -45,18 +43,19 @@ namespace ImageSharp.Tests
[MemberData(nameof(OilPaintValues))] [MemberData(nameof(OilPaintValues))]
public void ImageShouldApplyOilPaintFilterInBox(Tuple<int, int> value) public void ImageShouldApplyOilPaintFilterInBox(Tuple<int, int> value)
{ {
string path = CreateOutputDirectory("OilPaint"); string path = this.CreateOutputDirectory("OilPaint");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value + "-InBox"); string filename = file.GetFileName(value + "-InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
if (image.Width > value.Item2 && image.Height > value.Item2)
{ {
using (FileStream output = File.OpenWrite($"{path}/{filename}")) if (image.Width > value.Item2 && image.Height > value.Item2)
{ {
image.OilPaint(value.Item1, value.Item2, new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)).Save(output); using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.OilPaint(value.Item1, value.Item2, new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)).Save(output);
}
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/PadTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyPadSampler() public void ImageShouldApplyPadSampler()
{ {
string path = CreateOutputDirectory("Pad"); string path = this.CreateOutputDirectory("Pad");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Pad(image.Width + 50, image.Height + 50) image.Pad(image.Width + 50, image.Height + 50).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs

@ -41,17 +41,15 @@ namespace ImageSharp.Tests
[MemberData(nameof(PixelateValues))] [MemberData(nameof(PixelateValues))]
public void ImageShouldApplyPixelateFilterInBox(int value) public void ImageShouldApplyPixelateFilterInBox(int value)
{ {
string path = CreateOutputDirectory("Pixelate"); string path = this.CreateOutputDirectory("Pixelate");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value + "-InBox"); string filename = file.GetFileName(value + "-InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Pixelate(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)) image.Pixelate(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyPolaroidFilter() public void ImageShouldApplyPolaroidFilter()
{ {
string path = CreateOutputDirectory("Polaroid"); string path = this.CreateOutputDirectory("Polaroid");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Polaroid() image.Polaroid().Save(output);
.Save(output);
} }
} }
} }

76
tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs

@ -42,12 +42,10 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Resize(image.Width / 2, image.Height / 2, sampler, true) image.Resize(image.Width / 2, image.Height / 2, sampler, true).Save(output);
.Save(output);
} }
} }
} }
@ -63,12 +61,10 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Resize(image.Width / 3, 0, sampler, false) image.Resize(image.Width / 3, 0, sampler, false).Save(output);
.Save(output);
} }
} }
} }
@ -84,12 +80,10 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Resize(0, image.Height / 3, sampler, false) image.Resize(0, image.Height / 3, sampler, false).Save(output);
.Save(output);
} }
} }
} }
@ -105,18 +99,16 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size(image.Width / 2, image.Height) Size = new Size(image.Width / 2, image.Height)
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -132,18 +124,16 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size(image.Width, image.Height / 2) Size = new Size(image.Width, image.Height / 2)
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -159,18 +149,16 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Size = new Size(image.Width + 200, image.Height), Size = new Size(image.Width + 200, image.Height),
Mode = ResizeMode.Pad Mode = ResizeMode.Pad
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -186,19 +174,17 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size(image.Width + 200, image.Height + 200), Size = new Size(image.Width + 200, image.Height + 200),
Mode = ResizeMode.BoxPad Mode = ResizeMode.BoxPad
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -214,19 +200,17 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size(300, 300), Size = new Size(300, 300),
Mode = ResizeMode.Max Mode = ResizeMode.Max
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -242,19 +226,17 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * 95F)), Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)),
Mode = ResizeMode.Min Mode = ResizeMode.Min
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }
@ -270,19 +252,17 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(name); string filename = file.GetFileName(name);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions
{ {
Sampler = sampler, Sampler = sampler,
Size = new Size(image.Width / 2, image.Height), Size = new Size(image.Width / 2, image.Height),
Mode = ResizeMode.Stretch Mode = ResizeMode.Stretch
}; };
image.Resize(options) image.Resize(options).Save(output);
.Save(output);
} }
} }
} }

10
tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs

@ -22,20 +22,18 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("RotateFlipValues")] [MemberData(nameof(RotateFlipValues))]
public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType) public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType)
{ {
string path = CreateOutputDirectory("RotateFlip"); string path = this.CreateOutputDirectory("RotateFlip");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(rotateType + "-" + flipType); string filename = file.GetFileName(rotateType + "-" + flipType);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.RotateFlip(rotateType, flipType) image.RotateFlip(rotateType, flipType).Save(output);
.Save(output);
} }
} }
} }

20
tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs

@ -28,39 +28,35 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("RotateFloatValues")] [MemberData(nameof(RotateFloatValues))]
public void ImageShouldApplyRotateSampler(float value) public void ImageShouldApplyRotateSampler(float value)
{ {
string path = CreateOutputDirectory("Rotate"); string path = this.CreateOutputDirectory("Rotate");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Rotate(value) image.Rotate(value).Save(output);
.Save(output);
} }
} }
} }
[Theory] [Theory]
[MemberData("RotateEnumValues")] [MemberData(nameof(RotateEnumValues))]
public void ImageShouldApplyRotateSampler(RotateType value) public void ImageShouldApplyRotateSampler(RotateType value)
{ {
string path = CreateOutputDirectory("Rotate"); string path = this.CreateOutputDirectory("Rotate");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Rotate(value) image.Rotate(value).Save(output);
.Save(output);
} }
} }
} }

8
tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs

@ -19,7 +19,7 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("SaturationValues")] [MemberData(nameof(SaturationValues))]
public void ImageShouldApplySaturationFilter(int value) public void ImageShouldApplySaturationFilter(int value)
{ {
string path = CreateOutputDirectory("Saturation"); string path = CreateOutputDirectory("Saturation");
@ -27,12 +27,10 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(value); string filename = file.GetFileName(value);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Saturation(value) image.Saturation(value).Save(output);
.Save(output);
} }
} }
} }

6
tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs

@ -18,12 +18,10 @@ namespace ImageSharp.Tests
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Sepia() image.Sepia().Save(output);
.Save(output);
} }
} }
} }

12
tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs

@ -19,22 +19,20 @@ namespace ImageSharp.Tests
}; };
[Theory] [Theory]
[MemberData("SkewValues")] [MemberData(nameof(SkewValues))]
public void ImageShouldApplySkewSampler(float x, float y) public void ImageShouldApplySkewSampler(float x, float y)
{ {
string path = CreateOutputDirectory("Skew"); string path = this.CreateOutputDirectory("Skew");
// Matches live example // Matches live example
// http://www.w3schools.com/css/tryit.asp?filename=trycss3_transform_skew // http://www.w3schools.com/css/tryit.asp?filename=trycss3_transform_skew
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName(x + "-" + y); string filename = file.GetFileName(x + "-" + y);
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Skew(x, y) image.Skew(x, y).Save(output);
.Save(output);
} }
} }
} }

31
tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs

@ -14,16 +14,14 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyVignetteFilter() public void ImageShouldApplyVignetteFilter()
{ {
string path = CreateOutputDirectory("Vignette"); string path = this.CreateOutputDirectory("Vignette");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{ {
image.Vignette() image.Vignette().Save(output);
.Save(output);
} }
} }
} }
@ -31,17 +29,15 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyVignetteFilterColor() public void ImageShouldApplyVignetteFilterColor()
{ {
string path = CreateOutputDirectory("Vignette"); string path = this.CreateOutputDirectory("Vignette");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("Color"); string filename = file.GetFileName("Color");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Vignette(Color.HotPink) image.Vignette(Color.HotPink).Save(output);
.Save(output);
} }
} }
} }
@ -49,17 +45,15 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyVignetteFilterRadius() public void ImageShouldApplyVignetteFilterRadius()
{ {
string path = CreateOutputDirectory("Vignette"); string path = this.CreateOutputDirectory("Vignette");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("Radius"); string filename = file.GetFileName("Radius");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Vignette(image.Width / 4, image.Height / 4) image.Vignette(image.Width / 4F, image.Height / 4F).Save(output);
.Save(output);
} }
} }
} }
@ -67,17 +61,16 @@ namespace ImageSharp.Tests
[Fact] [Fact]
public void ImageShouldApplyVignetteFilterInBox() public void ImageShouldApplyVignetteFilterInBox()
{ {
string path = CreateOutputDirectory("Vignette"); string path = this.CreateOutputDirectory("Vignette");
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
string filename = file.GetFileName("InBox"); string filename = file.GetFileName("InBox");
Image image = file.CreateImage(); using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}")) using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{ {
image.Vignette(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) image.Vignette(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2))
.Save(output); .Save(output);
} }
} }
} }

3
tests/ImageSharp.Tests/Profiles/Exif/ExifProfileTests.cs

@ -31,6 +31,8 @@ namespace ImageSharp.Tests
ExifValue value = image.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright); ExifValue value = image.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright);
TestValue(value, "Dirk Lemstra"); TestValue(value, "Dirk Lemstra");
} }
[Fact] [Fact]
@ -247,6 +249,7 @@ namespace ImageSharp.Tests
using (MemoryStream memStream = new MemoryStream()) using (MemoryStream memStream = new MemoryStream())
{ {
image.SaveAsJpeg(memStream); image.SaveAsJpeg(memStream);
image.Dispose();
memStream.Position = 0; memStream.Position = 0;
return new Image(memStream); return new Image(memStream);

2
tests/ImageSharp.Tests/Profiles/Exif/ExifTagDescriptionAttributeTests.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Tests
public class ExifDescriptionAttributeTests public class ExifDescriptionAttributeTests
{ {
[Fact] [Fact]
public void Test_ExifTag() public void TestExifTag()
{ {
var exifProfile = new ExifProfile(); var exifProfile = new ExifProfile();

7
tests/ImageSharp.Tests/Profiles/Exif/ExifValueTests.cs

@ -12,9 +12,12 @@ namespace ImageSharp.Tests
{ {
private static ExifValue GetExifValue() private static ExifValue GetExifValue()
{ {
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); ExifProfile profile;
using (Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage())
{
profile = image.ExifProfile;
}
ExifProfile profile = image.ExifProfile;
Assert.NotNull(profile); Assert.NotNull(profile);
return profile.Values.First(); return profile.Values.First();

Loading…
Cancel
Save