Browse Source

Merge pull request #667 from SixLabors/af/drop-paralleloptions

Replace Configuration.ParallelOptions with Configuration.MaxDegreeOfParallelism
af/merge-core
Anton Firsov 8 years ago
committed by GitHub
parent
commit
cd155bf5be
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
  2. 8
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
  3. 22
      src/ImageSharp/Common/Extensions/ConfigurationExtensions.cs
  4. 6
      src/ImageSharp/Common/Helpers/ParallelFor.cs
  5. 21
      src/ImageSharp/Configuration.cs
  6. 2
      src/ImageSharp/ImageFrame{TPixel}.cs
  7. 30
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  8. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  9. 14
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  10. 4
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
  11. 4
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs
  12. 4
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs
  13. 2
      src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs
  14. 4
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs
  15. 4
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs
  16. 30
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  17. 38
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  18. 8
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
  19. 4
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
  20. 8
      src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
  21. 8
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
  22. 8
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  23. 12
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  24. 16
      tests/ImageSharp.Benchmarks/Codecs/CopyPixels.cs
  25. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave.cs
  26. 4
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  27. 2
      tests/ImageSharp.Benchmarks/Samplers/Resize.cs
  28. 25
      tests/ImageSharp.Tests/ConfigurationTests.cs
  29. 6
      tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs
  30. 14
      tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

4
src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs

@ -139,10 +139,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{ {
amount.GetSpan().Fill(this.Opacity); amount.GetSpan().Fill(this.Opacity);
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width); Span<TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width);

8
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs

@ -54,10 +54,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
// If there's no reason for blending, then avoid it. // If there's no reason for blending, then avoid it.
if (this.IsSolidBrushWithoutBlending(out SolidBrush<TPixel> solidBrush)) if (this.IsSolidBrushWithoutBlending(out SolidBrush<TPixel> solidBrush))
{ {
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
source.GetPixelRowSpan(y).Slice(minX, width).Fill(solidBrush.Color); source.GetPixelRowSpan(y).Slice(minX, width).Fill(solidBrush.Color);
@ -84,10 +84,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{ {
amount.GetSpan().Fill(1f); amount.GetSpan().Fill(1f);
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
int offsetY = y - startY; int offsetY = y - startY;

22
src/ImageSharp/Common/Extensions/ConfigurationExtensions.cs

@ -0,0 +1,22 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Threading.Tasks;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Contains extension methods for <see cref="Configuration"/>
/// </summary>
internal static class ConfigurationExtensions
{
/// <summary>
/// Creates a <see cref="ParallelOptions"/> object based on <paramref name="configuration"/>,
/// having <see cref="ParallelOptions.MaxDegreeOfParallelism"/> set to <see cref="Configuration.MaxDegreeOfParallelism"/>
/// </summary>
public static ParallelOptions GetParallelOptions(this Configuration configuration)
{
return new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism };
}
}
}

6
src/ImageSharp/Common/Helpers/ParallelFor.cs

@ -11,11 +11,11 @@ namespace SixLabors.ImageSharp
internal static class ParallelFor internal static class ParallelFor
{ {
/// <summary> /// <summary>
/// Helper method to execute Parallel.For using the settings in <see cref="Configuration.ParallelOptions"/> /// Helper method to execute Parallel.For using the settings in <paramref name="configuration"/>
/// </summary> /// </summary>
public static void WithConfiguration(int fromInclusive, int toExclusive, Configuration configuration, Action<int> body) public static void WithConfiguration(int fromInclusive, int toExclusive, Configuration configuration, Action<int> body)
{ {
Parallel.For(fromInclusive, toExclusive, configuration.ParallelOptions, body); Parallel.For(fromInclusive, toExclusive, configuration.GetParallelOptions(), body);
} }
/// <summary> /// <summary>
@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp
where T : struct where T : struct
{ {
MemoryAllocator memoryAllocator = configuration.MemoryAllocator; MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
ParallelOptions parallelOptions = configuration.ParallelOptions; ParallelOptions parallelOptions = configuration.GetParallelOptions();
IMemoryOwner<T> InitBuffer() IMemoryOwner<T> InitBuffer()
{ {

21
src/ImageSharp/Configuration.cs

@ -27,6 +27,8 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance); private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance);
private int maxDegreeOfParallelism = Environment.ProcessorCount;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class. /// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary> /// </summary>
@ -55,9 +57,22 @@ namespace SixLabors.ImageSharp
public static Configuration Default { get; } = Lazy.Value; public static Configuration Default { get; } = Lazy.Value;
/// <summary> /// <summary>
/// Gets the global parallel options for processing tasks in parallel. /// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms
/// configured with this <see cref="Configuration"/> instance.
/// </summary> /// </summary>
public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; public int MaxDegreeOfParallelism
{
get => this.maxDegreeOfParallelism;
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism));
}
this.maxDegreeOfParallelism = value;
}
}
/// <summary> /// <summary>
/// Gets the currently registered <see cref="IImageFormat"/>s. /// Gets the currently registered <see cref="IImageFormat"/>s.
@ -114,7 +129,7 @@ namespace SixLabors.ImageSharp
{ {
return new Configuration return new Configuration
{ {
ParallelOptions = this.ParallelOptions, MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
ImageFormatsManager = this.ImageFormatsManager, ImageFormatsManager = this.ImageFormatsManager,
MemoryAllocator = this.MemoryAllocator, MemoryAllocator = this.MemoryAllocator,
ImageOperationsProvider = this.ImageOperationsProvider, ImageOperationsProvider = this.ImageOperationsProvider,

2
src/ImageSharp/ImageFrame{TPixel}.cs

@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp
this.MemoryAllocator = configuration.MemoryAllocator; this.MemoryAllocator = configuration.MemoryAllocator;
this.PixelBuffer = this.MemoryAllocator.Allocate2D<TPixel>(width, height); this.PixelBuffer = this.MemoryAllocator.Allocate2D<TPixel>(width, height);
this.MetaData = metaData; this.MetaData = metaData;
this.Clear(configuration.ParallelOptions, backgroundColor); this.Clear(configuration.GetParallelOptions(), backgroundColor);
} }
/// <summary> /// <summary>

30
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -70,25 +70,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
endY, endY,
configuration.ParallelOptions, configuration,
y => y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{ {
ref TPixel color = ref row[x]; Span<TPixel> row = source.GetPixelRowSpan(y);
color.ToRgba32(ref rgba); Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
// Convert to grayscale using ITU-R Recommendation BT.709 if required // Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B); float luminance = isAlphaOnly
color = luminance >= threshold ? upper : lower; ? rgba.A
} : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
}); color = luminance >= threshold ? upper : lower;
}
});
} }
} }
} }

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

@ -61,10 +61,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{ {
source.CopyTo(targetPixels); source.CopyTo(targetPixels);
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
endY, endY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

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

@ -43,12 +43,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{ {
ParallelOptions parallelOptions = configuration.ParallelOptions;
using (Buffer2D<TPixel> firstPassPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size())) using (Buffer2D<TPixel> firstPassPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{ {
this.ApplyConvolution(firstPassPixels, source.PixelBuffer, source.Bounds(), this.KernelX, parallelOptions); this.ApplyConvolution(firstPassPixels, source.PixelBuffer, source.Bounds(), this.KernelX, configuration);
this.ApplyConvolution(source.PixelBuffer, firstPassPixels, sourceRectangle, this.KernelY, parallelOptions); this.ApplyConvolution(source.PixelBuffer, firstPassPixels, sourceRectangle, this.KernelY, configuration);
} }
} }
@ -62,13 +60,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param> /// </param>
/// <param name="kernel">The kernel operator.</param> /// <param name="kernel">The kernel operator.</param>
/// <param name="parallelOptions">The parallel options</param> /// <param name="configuration">The <see cref="Configuration"/></param>
private void ApplyConvolution( private void ApplyConvolution(
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels, Buffer2D<TPixel> sourcePixels,
Rectangle sourceRectangle, Rectangle sourceRectangle,
DenseMatrix<float> kernel, DenseMatrix<float> kernel,
ParallelOptions parallelOptions) Configuration configuration)
{ {
int kernelHeight = kernel.Rows; int kernelHeight = kernel.Rows;
int kernelWidth = kernel.Columns; int kernelWidth = kernel.Columns;
@ -82,10 +80,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
int maxY = endY - 1; int maxY = endY - 1;
int maxX = endX - 1; int maxX = endX - 1;
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
endY, endY,
parallelOptions, configuration,
y => y =>
{ {
Span<TPixel> targetRow = targetPixels.GetRowSpan(y); Span<TPixel> targetRow = targetPixels.GetRowSpan(y);

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

@ -51,10 +51,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{ {
source.CopyTo(targetPixels); source.CopyTo(targetPixels);
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
endY, endY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

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

@ -133,10 +133,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
Buffer2D<TPixel> passPixels = pass.PixelBuffer; Buffer2D<TPixel> passPixels = pass.PixelBuffer;
Buffer2D<TPixel> targetPixels = source.PixelBuffer; Buffer2D<TPixel> targetPixels = source.PixelBuffer;
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
int offsetY = y - shiftY; int offsetY = y - shiftY;

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

@ -69,10 +69,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{ {
source.CopyTo(targetPixels); source.CopyTo(targetPixels);
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

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

@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
Parallel.ForEach( Parallel.ForEach(
range, range,
configuration.ParallelOptions, configuration.GetParallelOptions(),
y => y =>
{ {
int offsetY = y - startY; int offsetY = y - startY;

4
src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs

@ -41,10 +41,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
int endX = interest.Right; int endX = interest.Right;
Matrix4x4 matrix = this.Matrix; Matrix4x4 matrix = this.Matrix;
Parallel.For( ParallelFor.WithConfiguration(
startY, startY,
endY, endY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> row = source.GetPixelRowSpan(y); Span<TPixel> row = source.GetPixelRowSpan(y);

4
src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs

@ -81,10 +81,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
} }
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.GraphicsOptions.BlenderMode); PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.GraphicsOptions.BlenderMode);
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width); Span<TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);

30
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -122,27 +122,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
rowColorsSpan[i] = glowColor; rowColorsSpan[i] = glowColor;
} }
Parallel.For( ParallelFor.WithTemporaryBuffer<float>(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => width,
(y, amounts) =>
{ {
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width)) Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{ {
Span<float> amountsSpan = amounts.GetSpan(); float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
int offsetY = y - startY; amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
} }
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
}); });
} }
} }

38
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -124,27 +124,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
rowColorsSpan[i] = vignetteColor; rowColorsSpan[i] = vignetteColor;
} }
Parallel.For( ParallelFor.WithTemporaryBuffer<float>(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => width,
(y, amounts) =>
{ {
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width)) Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{ {
Span<float> amountsSpan = amounts.GetSpan(); float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
int offsetY = y - startY; amountsSpan[i] =
int offsetX = minX - startX; (this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(
for (int i = 0; i < width; i++) 0,
{ 1);
float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
} }
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.MemoryAllocator,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
}); });
} }
} }

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

@ -77,10 +77,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> destRow = destination.GetPixelRowSpan(y); Span<TPixel> destRow = destination.GetPixelRowSpan(y);
@ -115,10 +115,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height)) using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height))
using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height)) using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y)); ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));

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

@ -58,10 +58,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
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);
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y).Slice(minX); Span<TPixel> sourceRow = source.GetPixelRowSpan(y).Slice(minX);

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

@ -58,10 +58,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size())) using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
halfHeight, halfHeight,
configuration.ParallelOptions, configuration,
y => y =>
{ {
int newY = height - y - 1; int newY = height - y - 1;
@ -91,10 +91,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size())) using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

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

@ -74,10 +74,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> destRow = destination.GetPixelRowSpan(y); Span<TPixel> destRow = destination.GetPixelRowSpan(y);
@ -120,10 +120,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height)) using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height))
using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height)) using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y)); ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));

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

@ -270,10 +270,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
// Y coordinates of source points // Y coordinates of source points
@ -331,10 +331,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}); });
// Now process the rows. // Now process the rows.
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
// Ensure offsets are normalized for cropping and padding. // Ensure offsets are normalized for cropping and padding.

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

@ -147,10 +147,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int height = source.Height; int height = source.Height;
Rectangle destinationBounds = destination.Bounds(); Rectangle destinationBounds = destination.Bounds();
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
@ -179,10 +179,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int width = source.Width; int width = source.Width;
int height = source.Height; int height = source.Height;
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
@ -207,10 +207,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int height = source.Height; int height = source.Height;
Rectangle destinationBounds = destination.Bounds(); Rectangle destinationBounds = destination.Bounds();
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
height, height,
configuration.ParallelOptions, configuration,
y => y =>
{ {
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

16
tests/ImageSharp.Benchmarks/Codecs/CopyPixels.cs

@ -24,10 +24,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{ {
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer();
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer(); Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer();
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
source.Height, source.Height,
Configuration.Default.ParallelOptions, Configuration.Default,
y => y =>
{ {
for (int x = 0; x < source.Width; x++) for (int x = 0; x < source.Width; x++)
@ -48,10 +48,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{ {
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer();
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer(); Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer();
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
source.Height, source.Height,
Configuration.Default.ParallelOptions, Configuration.Default,
y => y =>
{ {
Span<Rgba32> sourceRow = sourcePixels.GetRowSpan(y); Span<Rgba32> sourceRow = sourcePixels.GetRowSpan(y);
@ -73,10 +73,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
using (var source = new Image<Rgba32>(1024, 768)) using (var source = new Image<Rgba32>(1024, 768))
using (var target = new Image<Rgba32>(1024, 768)) using (var target = new Image<Rgba32>(1024, 768))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
source.Height, source.Height,
Configuration.Default.ParallelOptions, Configuration.Default,
y => y =>
{ {
for (int x = 0; x < source.Width; x++) for (int x = 0; x < source.Width; x++)
@ -95,10 +95,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
using (var source = new Image<Rgba32>(1024, 768)) using (var source = new Image<Rgba32>(1024, 768))
using (var target = new Image<Rgba32>(1024, 768)) using (var target = new Image<Rgba32>(1024, 768))
{ {
Parallel.For( ParallelFor.WithConfiguration(
0, 0,
source.Height, source.Height,
Configuration.Default.ParallelOptions, Configuration.Default,
y => y =>
{ {
Span<Rgba32> sourceRow = source.Frames.RootFrame.GetPixelRowSpan(y); Span<Rgba32> sourceRow = source.Frames.RootFrame.GetPixelRowSpan(y);

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[GlobalSetup] [GlobalSetup]
public void Setup() public void Setup()
{ {
this.configuration.ParallelOptions.MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism =
this.EnableParallelExecution ? Environment.ProcessorCount : 1; this.EnableParallelExecution ? Environment.ProcessorCount : 1;
if (this.sourceBytes == null) if (this.sourceBytes == null)

4
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -109,10 +109,10 @@ namespace SixLabors.ImageSharp.Benchmarks
Buffer2D<TPixel> sourcePixels = source.PixelBuffer; Buffer2D<TPixel> sourcePixels = source.PixelBuffer;
rowColors.GetSpan().Fill(glowColor); rowColors.GetSpan().Fill(glowColor);
Parallel.For( ParallelFor.WithConfiguration(
minY, minY,
maxY, maxY,
configuration.ParallelOptions, configuration,
y => y =>
{ {
int offsetY = y - startY; int offsetY = y - startY;

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

@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Benchmarks
[GlobalSetup] [GlobalSetup]
public void Setup() public void Setup()
{ {
this.configuration.ParallelOptions.MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism =
this.EnableParallelExecution ? Environment.ProcessorCount : 1; this.EnableParallelExecution ? Environment.ProcessorCount : 1;
} }

25
tests/ImageSharp.Tests/ConfigurationTests.cs

@ -10,6 +10,7 @@ using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Moq; using Moq;
using Xunit; using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests namespace SixLabors.ImageSharp.Tests
{ {
@ -45,15 +46,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.True(Configuration.Default != null); Assert.True(Configuration.Default != null);
} }
/// <summary>
/// Test that the default configuration parallel options is not null.
/// </summary>
[Fact]
public void TestDefaultConfigurationParallelOptionsIsNotNull()
{
Assert.True(Configuration.Default.ParallelOptions != null);
}
/// <summary> /// <summary>
/// Test that the default configuration read origin options is set to begin. /// Test that the default configuration read origin options is set to begin.
/// </summary> /// </summary>
@ -70,9 +62,22 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void TestDefaultConfigurationMaxDegreeOfParallelism() public void TestDefaultConfigurationMaxDegreeOfParallelism()
{ {
Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount); Assert.True(Configuration.Default.MaxDegreeOfParallelism == Environment.ProcessorCount);
var cfg = new Configuration();
Assert.True(cfg.MaxDegreeOfParallelism == Environment.ProcessorCount);
} }
[Theory]
[InlineData(0)]
[InlineData(-42)]
public void Set_MaxDegreeOfParallelism_ToNonPositiveValue_Throws(int value)
{
var cfg = new Configuration();
Assert.Throws<ArgumentOutOfRangeException>(() => cfg.MaxDegreeOfParallelism = value);
}
[Fact] [Fact]
public void ConstructorCallConfigureOnFormatProvider() public void ConstructorCallConfigureOnFormatProvider()
{ {

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

@ -184,7 +184,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons");
var config = Configuration.CreateDefaultInstance(); var config = Configuration.CreateDefaultInstance();
config.ParallelOptions.MaxDegreeOfParallelism = 1; config.MaxDegreeOfParallelism = 1;
using (var image = new Image<Rgba32>(config, 100, 100)) using (var image = new Image<Rgba32>(config, 100, 100))
{ {
image.Mutate(x => x image.Mutate(x => x
@ -200,7 +200,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons");
var config = Configuration.CreateDefaultInstance(); var config = Configuration.CreateDefaultInstance();
config.ParallelOptions.MaxDegreeOfParallelism = 1; config.MaxDegreeOfParallelism = 1;
using (var image = new Image<Rgba32>(config, 100, 100)) using (var image = new Image<Rgba32>(config, 100, 100))
{ {
image.Mutate(x => x image.Mutate(x => x
@ -217,7 +217,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons");
var config = Configuration.CreateDefaultInstance(); var config = Configuration.CreateDefaultInstance();
config.ParallelOptions.MaxDegreeOfParallelism = 1; config.MaxDegreeOfParallelism = 1;
using (var image = new Image<Rgba32>(config, 200, 200)) using (var image = new Image<Rgba32>(config, 200, 200))
{ {
image.Mutate(x => x image.Mutate(x => x

14
tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

@ -8,6 +8,7 @@ using System.Drawing.Imaging;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Shapes; using SixLabors.Shapes;
@ -102,6 +103,11 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WrapSystemDrawingBitmap_WhenObserved() public void WrapSystemDrawingBitmap_WhenObserved()
{ {
if (ShouldSkipBitmapTest)
{
return;
}
using (var bmp = new Bitmap(51, 23)) using (var bmp = new Bitmap(51, 23))
{ {
using (var memoryManager = new BitmapMemoryManager(bmp)) using (var memoryManager = new BitmapMemoryManager(bmp))
@ -130,6 +136,11 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WrapSystemDrawingBitmap_WhenOwned() public void WrapSystemDrawingBitmap_WhenOwned()
{ {
if (ShouldSkipBitmapTest)
{
return;
}
using (var bmp = new Bitmap(51, 23)) using (var bmp = new Bitmap(51, 23))
{ {
var memoryManager = new BitmapMemoryManager(bmp); var memoryManager = new BitmapMemoryManager(bmp);
@ -151,6 +162,9 @@ namespace SixLabors.ImageSharp.Tests
bmp.Save(fn, ImageFormat.Bmp); bmp.Save(fn, ImageFormat.Bmp);
} }
} }
private static bool ShouldSkipBitmapTest =>
!TestEnvironment.Is64BitProcess || TestHelpers.ImageSharpBuiltAgainst != "netcoreapp2.1";
} }
} }
} }
Loading…
Cancel
Save