diff --git a/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs b/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs
index 89d5fc18d8..516c1446d2 100644
--- a/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs
+++ b/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs
@@ -12,7 +12,15 @@ namespace SixLabors.ImageSharp.ParallelUtils
///
internal struct ParallelExecutionSettings
{
- public ParallelExecutionSettings(int maxDegreeOfParallelism, int minimumPixelsProcessedPerTask, MemoryAllocator memoryAllocator)
+ ///
+ /// Default value for .
+ ///
+ public const int DefaultMinimumPixelsProcessedPerTask = 2048;
+
+ public ParallelExecutionSettings(
+ int maxDegreeOfParallelism,
+ int minimumPixelsProcessedPerTask,
+ MemoryAllocator memoryAllocator)
{
this.MaxDegreeOfParallelism = maxDegreeOfParallelism;
this.MinimumPixelsProcessedPerTask = minimumPixelsProcessedPerTask;
@@ -20,7 +28,7 @@ namespace SixLabors.ImageSharp.ParallelUtils
}
public ParallelExecutionSettings(int maxDegreeOfParallelism, MemoryAllocator memoryAllocator)
- : this(maxDegreeOfParallelism, 2048, memoryAllocator)
+ : this(maxDegreeOfParallelism, DefaultMinimumPixelsProcessedPerTask, memoryAllocator)
{
}
@@ -37,5 +45,13 @@ namespace SixLabors.ImageSharp.ParallelUtils
/// Initialized with 2048 by default, the optimum value is operation specific.
///
public int MinimumPixelsProcessedPerTask { get; }
+
+ public ParallelExecutionSettings MultiplyMinimumPixelsPerTask(int multiplier)
+ {
+ return new ParallelExecutionSettings(
+ this.MaxDegreeOfParallelism,
+ this.MinimumPixelsProcessedPerTask * multiplier,
+ this.MemoryAllocator);
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
index 0c52123755..bb26216ece 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
@@ -4,8 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@@ -53,21 +53,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return;
}
- int minY = Math.Max(this.CropRectangle.Y, sourceRectangle.Y);
- int maxY = Math.Min(this.CropRectangle.Bottom, sourceRectangle.Bottom);
- int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
- int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);
+ var rect = Rectangle.Intersect(this.CropRectangle, sourceRectangle);
- ParallelFor.WithConfiguration(
- minY,
- maxY,
- configuration,
- y =>
- {
- Span sourceRow = source.GetPixelRowSpan(y).Slice(minX);
- Span targetRow = destination.GetPixelRowSpan(y - minY);
- sourceRow.Slice(0, maxX - minX).CopyTo(targetRow);
- });
+ // Copying is cheap, we should process more pixels per task:
+ ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4);
+
+ ParallelHelper.IterateRows(
+ rect,
+ parallelSettings,
+ rows =>
+ {
+ for (int y = rows.Min; y < rows.Max; y++)
+ {
+ Span sourceRow = source.GetPixelRowSpan(y).Slice(rect.Left);
+ Span targetRow = destination.GetPixelRowSpan(y - rect.Top);
+ sourceRow.Slice(0, rect.Width).CopyTo(targetRow);
+ }
+ });
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
index cea6df391f..442873676f 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
@@ -57,8 +57,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int height = source.Height;
int halfHeight = (int)Math.Ceiling(source.Height * .5F);
+
using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Size()))
{
+
+
ParallelFor.WithConfiguration(
0,
halfHeight,
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
index d7e7a724c4..3c932bfaa6 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
@@ -5,23 +5,24 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit;
+
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
- using SixLabors.ImageSharp.Processing;
-
+ [GroupOutput("Transforms")]
public class FlipTests
{
- public static readonly TheoryData FlipValues
- = new TheoryData
- {
- { FlipMode.None },
- { FlipMode.Vertical },
- { FlipMode.Horizontal },
- };
+ public static readonly TheoryData FlipValues =
+ new TheoryData
+ {
+ FlipMode.None,
+ FlipMode.Vertical,
+ FlipMode.Horizontal,
+ };
[Theory]
+ [WithTestPatternImages(nameof(FlipValues), 20, 37, PixelTypes.Rgba32)]
[WithTestPatternImages(nameof(FlipValues), 53, 37, PixelTypes.Rgba32)]
[WithTestPatternImages(nameof(FlipValues), 17, 32, PixelTypes.Rgba32)]
public void Flip(TestImageProvider provider, FlipMode flipMode)
diff --git a/tests/Images/External b/tests/Images/External
index 2841a79efd..c1e14c0e43 160000
--- a/tests/Images/External
+++ b/tests/Images/External
@@ -1 +1 @@
-Subproject commit 2841a79efd68d47c6552ce857869eb0d80f8de75
+Subproject commit c1e14c0e431066c57585f255d3feb8d3a1860d50