diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
index c539861f9b..1b6438bf3f 100644
--- a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
@@ -110,10 +110,10 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
///
- /// Gets the size of the target image.
+ /// Gets the size of the destination image.
///
/// The .
- protected abstract Size GetTargetSize();
+ protected abstract Size GetDestinationSize();
///
/// This method is called before the process is applied to prepare the processor.
@@ -168,21 +168,21 @@ namespace SixLabors.ImageSharp.Processing.Processors
private Image CreateTarget()
{
Image source = this.Source;
- Size targetSize = this.GetTargetSize();
+ Size destinationSize = this.GetDestinationSize();
// We will always be creating the clone even for mutate because we may need to resize the canvas.
- var targetFrames = new ImageFrame[source.Frames.Count];
- for (int i = 0; i < targetFrames.Length; i++)
+ var destinationFrames = new ImageFrame[source.Frames.Count];
+ for (int i = 0; i < destinationFrames.Length; i++)
{
- targetFrames[i] = new ImageFrame(
+ destinationFrames[i] = new ImageFrame(
this.Configuration,
- targetSize.Width,
- targetSize.Height,
+ destinationSize.Width,
+ destinationSize.Height,
source.Frames[i].Metadata.DeepClone());
}
// Use the overload to prevent an extra frame being added.
- return new Image(this.Configuration, source.Metadata.DeepClone(), targetFrames);
+ return new Image(this.Configuration, source.Metadata.DeepClone(), destinationFrames);
}
private void CheckFrameCount(Image a, Image b)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
index 130cc1bf05..9d01c049c2 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.resampler = definition.Sampler;
}
- protected override Size GetTargetSize() => this.targetSize;
+ protected override Size GetDestinationSize() => this.targetSize;
///
protected override void OnFrameApply(ImageFrame source, ImageFrame destination)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
index e8eeea3cb1..a80eef2bcd 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
@@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
=> this.cropRectangle = definition.CropRectangle;
///
- protected override Size GetTargetSize() => new Size(this.cropRectangle.Width, this.cropRectangle.Height);
+ protected override Size GetDestinationSize() => new Size(this.cropRectangle.Width, this.cropRectangle.Height);
///
protected override void OnFrameApply(ImageFrame source, ImageFrame destination)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/IResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/IResampler.cs
index fb095b70ab..c7557461a8 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/IResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/IResampler.cs
@@ -25,6 +25,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
float GetValue(float x);
+ ///
+ /// Applies an resizing transformation upon an image.
+ ///
+ /// The pixel format.
+ /// The configuration.
+ /// The source image.
+ /// The destination image.
+ /// The source bounds.
+ /// The target location.
+ /// Whether to compress or expand individual pixel color values on processing.
+ void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle targetRectangle,
+ bool compand)
+ where TPixel : struct, IPixel;
+
///
/// Applies an affine transformation upon an image.
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
index 50315ac95c..afc4658b44 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.resampler = definition.Sampler;
}
- protected override Size GetTargetSize() => this.targetSize;
+ protected override Size GetDestinationSize() => this.targetSize;
///
protected override void OnFrameApply(ImageFrame source, ImageFrame destination)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BicubicResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BicubicResampler.cs
index ea68715753..5f9669f6f8 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BicubicResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BicubicResampler.cs
@@ -41,6 +41,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BoxResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BoxResampler.cs
index 49b53378f9..ecaa28c804 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BoxResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/BoxResampler.cs
@@ -28,6 +28,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CatmullRomResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CatmullRomResampler.cs
index 5a2992595d..f62b7d989c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CatmullRomResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CatmullRomResampler.cs
@@ -28,6 +28,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/HermiteResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/HermiteResampler.cs
index 80aa69acd6..883d4b684a 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/HermiteResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/HermiteResampler.cs
@@ -27,6 +27,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos2Resampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos2Resampler.cs
index 3228a709d2..93174a23a1 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos2Resampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos2Resampler.cs
@@ -34,6 +34,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos3Resampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos3Resampler.cs
index a9388575be..6c008be630 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos3Resampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos3Resampler.cs
@@ -34,6 +34,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos5Resampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos5Resampler.cs
index 7662f26160..56da01fb27 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos5Resampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos5Resampler.cs
@@ -34,6 +34,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos8Resampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos8Resampler.cs
index e886f41db9..d24c7a1f08 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos8Resampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/Lanczos8Resampler.cs
@@ -34,6 +34,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/MitchellNetravaliResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/MitchellNetravaliResampler.cs
index ef97be92b5..e67e50ab0b 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/MitchellNetravaliResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/MitchellNetravaliResampler.cs
@@ -25,6 +25,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/NearestNeighborResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/NearestNeighborResampler.cs
index e4cec5f4d5..94b0b0405f 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/NearestNeighborResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/NearestNeighborResampler.cs
@@ -20,6 +20,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(InliningOptions.ShortMethod)]
public float GetValue(float x) => x;
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxResampler.cs
index 6d9e7641e0..1b4d84e5a0 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxResampler.cs
@@ -26,6 +26,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxSharpResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxSharpResampler.cs
index eaf5fa6e80..52991a6493 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxSharpResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/RobidouxSharpResampler.cs
@@ -26,6 +26,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/SplineResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/SplineResampler.cs
index d2608b2faa..a21ed495bc 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/SplineResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/SplineResampler.cs
@@ -26,6 +26,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return ImageMaths.GetBcValue(x, B, C);
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/TriangleResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/TriangleResampler.cs
index b403621241..c8409e1859 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/TriangleResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/TriangleResampler.cs
@@ -34,6 +34,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs
index 8a92ea7c00..673cbd5d74 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs
@@ -33,6 +33,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return 0F;
}
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ApplyResizeTransform(
+ Configuration configuration,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TPixel : struct, IPixel => ResamplerExtensions.ApplyResizeTransform(
+ configuration,
+ in this,
+ source,
+ destination,
+ sourceRectangle,
+ destinationRectangle,
+ compand);
+
///
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyAffineTransform(
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs
new file mode 100644
index 0000000000..b681a436cd
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs
@@ -0,0 +1,227 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Transforms
+{
+ ///
+ /// Extensions for .
+ ///
+ public static partial class ResamplerExtensions
+ {
+ ///
+ /// Applies an resizing transformation upon an image.
+ ///
+ /// The type of sampler.
+ /// The pixel format.
+ /// The configuration.
+ /// The pixel sampler.
+ /// The source image.
+ /// The destination image.
+ /// The source bounds.
+ /// The destination location.
+ /// Whether to compress or expand individual pixel color values on processing.
+ public static void ApplyResizeTransform(
+ Configuration configuration,
+ in TResampler sampler,
+ Image source,
+ Image destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ bool compand)
+ where TResampler : unmanaged, IResampler
+ where TPixel : struct, IPixel
+ {
+ // Handle resize dimensions identical to the original
+ if (source.Width == destination.Width
+ && source.Height == destination.Height
+ && sourceRectangle == destinationRectangle)
+ {
+ for (int i = 0; i < source.Frames.Count; i++)
+ {
+ ImageFrame sourceFrame = source.Frames[i];
+ ImageFrame destinationFrame = destination.Frames[i];
+
+ // The cloned will be blank here copy all the pixel data over
+ sourceFrame.GetPixelMemoryGroup().CopyTo(destinationFrame.GetPixelMemoryGroup());
+ }
+
+ return;
+ }
+
+ var interest = Rectangle.Intersect(destinationRectangle, destination.Bounds());
+
+ if (sampler is NearestNeighborResampler)
+ {
+ for (int i = 0; i < source.Frames.Count; i++)
+ {
+ ImageFrame sourceFrame = source.Frames[i];
+ ImageFrame destinationFrame = destination.Frames[i];
+
+ ApplyNNResizeFrameTransform(
+ configuration,
+ sourceFrame,
+ destinationFrame,
+ sourceRectangle,
+ destinationRectangle,
+ interest);
+ }
+
+ return;
+ }
+
+ // Since all image frame dimensions have to be the same we can calculate
+ // the kernel maps and reuse for all frames.
+ MemoryAllocator allocator = configuration.MemoryAllocator;
+ using var horizontalKernelMap = ResizeKernelMap.Calculate(
+ in sampler,
+ destinationRectangle.Width,
+ sourceRectangle.Width,
+ allocator);
+
+ using var verticalKernelMap = ResizeKernelMap.Calculate(
+ in sampler,
+ destinationRectangle.Height,
+ sourceRectangle.Height,
+ allocator);
+
+ for (int i = 0; i < source.Frames.Count; i++)
+ {
+ ImageFrame sourceFrame = source.Frames[i];
+ ImageFrame destinationFrame = destination.Frames[i];
+
+ ApplyResizeFrameTransform(
+ configuration,
+ sourceFrame,
+ destinationFrame,
+ horizontalKernelMap,
+ verticalKernelMap,
+ sourceRectangle,
+ destinationRectangle,
+ interest,
+ compand);
+ }
+ }
+
+ private static void ApplyNNResizeFrameTransform(
+ Configuration configuration,
+ ImageFrame source,
+ ImageFrame destination,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ Rectangle interest)
+ where TPixel : struct, IPixel
+ {
+ // Scaling factors
+ float widthFactor = sourceRectangle.Width / (float)destinationRectangle.Width;
+ float heightFactor = sourceRectangle.Height / (float)destinationRectangle.Height;
+
+ var operation = new NNRowIntervalOperation(
+ sourceRectangle,
+ destinationRectangle,
+ widthFactor,
+ heightFactor,
+ source,
+ destination);
+
+ ParallelRowIterator.IterateRows(
+ configuration,
+ interest,
+ in operation);
+ }
+
+ private static void ApplyResizeFrameTransform(
+ Configuration configuration,
+ ImageFrame source,
+ ImageFrame destination,
+ ResizeKernelMap horizontalKernelMap,
+ ResizeKernelMap verticalKernelMap,
+ Rectangle sourceRectangle,
+ Rectangle destinationRectangle,
+ Rectangle interest,
+ bool compand)
+ where TResampler : unmanaged, IResampler
+ where TPixel : struct, IPixel
+ {
+ PixelConversionModifiers conversionModifiers =
+ PixelConversionModifiers.Premultiply.ApplyCompanding(compand);
+
+ BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle);
+
+ // To reintroduce parallel processing, we would launch multiple workers
+ // for different row intervals of the image.
+ using (var worker = new ResizeWorker(
+ configuration,
+ sourceArea,
+ conversionModifiers,
+ horizontalKernelMap,
+ verticalKernelMap,
+ destination.Width,
+ interest,
+ destinationRectangle.Location))
+ {
+ worker.Initialize();
+
+ var workingInterval = new RowInterval(interest.Top, interest.Bottom);
+ worker.FillDestinationPixels(workingInterval, destination.PixelBuffer);
+ }
+ }
+
+ private readonly struct NNRowIntervalOperation : IRowIntervalOperation
+ where TPixel : struct, IPixel
+ {
+ private readonly Rectangle sourceBounds;
+ private readonly Rectangle destinationBounds;
+ private readonly float widthFactor;
+ private readonly float heightFactor;
+ private readonly ImageFrame source;
+ private readonly ImageFrame destination;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public NNRowIntervalOperation(
+ Rectangle sourceBounds,
+ Rectangle destinationBounds,
+ float widthFactor,
+ float heightFactor,
+ ImageFrame source,
+ ImageFrame destination)
+ {
+ this.sourceBounds = sourceBounds;
+ this.destinationBounds = destinationBounds;
+ this.widthFactor = widthFactor;
+ this.heightFactor = heightFactor;
+ this.source = source;
+ this.destination = destination;
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(in RowInterval rows)
+ {
+ int sourceX = this.sourceBounds.X;
+ int sourceY = this.sourceBounds.Y;
+ int destX = this.destinationBounds.X;
+ int destY = this.destinationBounds.Y;
+ int destLeft = this.destinationBounds.Left;
+ int destRight = this.destinationBounds.Right;
+
+ for (int y = rows.Min; y < rows.Max; y++)
+ {
+ // Y coordinates of source points
+ Span sourceRow = this.source.GetPixelRowSpan((int)(((y - destY) * this.heightFactor) + sourceY));
+ Span targetRow = this.destination.GetPixelRowSpan(y);
+
+ for (int x = destLeft; x < destRight; x++)
+ {
+ // X coordinates of source points
+ targetRow[x] = sourceRow[(int)(((x - destX) * this.widthFactor) + sourceX)];
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
index 14bf552b9d..83bee91114 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
///
- /// Points to a collection of of weights allocated in .
+ /// Points to a collection of of weights allocated in .
///
internal readonly unsafe struct ResizeKernel
{
@@ -28,15 +28,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// Gets the start index for the destination row.
///
- public int StartIndex { get; }
+ public int StartIndex
+ {
+ [MethodImpl(InliningOptions.ShortMethod)]
+ get;
+ }
///
/// Gets the the length of the kernel.
///
- public int Length { get; }
+ public int Length
+ {
+ [MethodImpl(InliningOptions.ShortMethod)]
+ get;
+ }
///
- /// Gets the span representing the portion of the that this window covers.
+ /// Gets the span representing the portion of the that this window covers.
///
/// The .
///
@@ -81,6 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// Copy the contents of altering
/// to the value .
///
+ [MethodImpl(InliningOptions.ShortMethod)]
internal ResizeKernel AlterLeftValue(int left)
{
return new ResizeKernel(left, this.bufferPtr, this.Length);
@@ -96,4 +105,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs
index be2546369e..52a308cf2b 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs
@@ -1,19 +1,17 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
- ///
- /// Contains
- ///
- internal partial class ResizeKernelMap
+ internal partial class ResizeKernelMap
+ where TResampler : unmanaged, IResampler
{
///
- /// Memory-optimized where repeating rows are stored only once.
+ /// Memory-optimized where repeating rows are stored only once.
///
- private sealed class PeriodicKernelMap : ResizeKernelMap
+ private sealed class PeriodicKernelMap : ResizeKernelMap
{
private readonly int period;
@@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
public PeriodicKernelMap(
MemoryAllocator memoryAllocator,
- IResampler sampler,
+ TResampler sampler,
int sourceLength,
int destinationLength,
double ratio,
@@ -45,15 +43,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
internal override string Info => base.Info + $"|period:{this.period}|cornerInterval:{this.cornerInterval}";
- protected override void Initialize()
+ protected internal override void Initialize()
{
// Build top corner data + one period of the mosaic data:
int startOfFirstRepeatedMosaic = this.cornerInterval + this.period;
for (int i = 0; i < startOfFirstRepeatedMosaic; i++)
{
- ResizeKernel kernel = this.BuildKernel(i, i);
- this.kernels[i] = kernel;
+ this.kernels[i] = this.BuildKernel(i, i);
}
// Copy the mosaics:
@@ -70,10 +67,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int bottomStartData = this.cornerInterval + this.period;
for (int i = 0; i < this.cornerInterval; i++)
{
- ResizeKernel kernel = this.BuildKernel(bottomStartDest + i, bottomStartData + i);
- this.kernels[bottomStartDest + i] = kernel;
+ this.kernels[bottomStartDest + i] = this.BuildKernel(bottomStartDest + i, bottomStartData + i);
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs
index cc95169564..8432eb654c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs
@@ -5,20 +5,20 @@ using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
///
- /// Provides values from an optimized,
- /// contiguous memory region.
+ /// Provides resize kernel values from an optimized contiguous memory region.
///
- internal partial class ResizeKernelMap : IDisposable
+ /// The type of sampler.
+ internal partial class ResizeKernelMap : IDisposable
+ where TResampler : unmanaged, IResampler
{
private static readonly TolerantMath TolerantMath = TolerantMath.Default;
- private readonly IResampler sampler;
+ private readonly TResampler sampler;
private readonly int sourceLength;
@@ -34,12 +34,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ResizeKernel[] kernels;
+ private bool isDisposed;
+
// To avoid both GC allocations, and MemoryAllocator ceremony:
private readonly double[] tempValues;
private ResizeKernelMap(
MemoryAllocator memoryAllocator,
- IResampler sampler,
+ TResampler sampler,
int sourceLength,
int destinationLength,
int bufferHeight,
@@ -77,19 +79,34 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
$"radius:{this.radius}|sourceSize:{this.sourceLength}|destinationSize:{this.DestinationLength}|ratio:{this.ratio}|scale:{this.scale}";
///
- /// Disposes instance releasing it's backing buffer.
+ /// Disposes instance releasing it's backing buffer.
///
public void Dispose()
+ => this.Dispose(true);
+
+ ///
+ /// Disposes the object and frees resources for the Garbage Collector.
+ ///
+ /// Whether to dispose of managed and unmanaged objects.
+ protected virtual void Dispose(bool disposing)
{
- this.pinHandle.Dispose();
- this.data.Dispose();
+ if (!this.isDisposed)
+ {
+ this.isDisposed = true;
+
+ if (disposing)
+ {
+ this.pinHandle.Dispose();
+ this.data.Dispose();
+ }
+ }
}
///
/// Returns a for an index value between 0 and DestinationSize - 1.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public ref ResizeKernel GetKernel(int destIdx) => ref this.kernels[destIdx];
+ internal ref ResizeKernel GetKernel(int destIdx) => ref this.kernels[destIdx];
///
/// Computes the weights to apply at each pixel when resizing.
@@ -98,9 +115,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// The destination size
/// The source size
/// The to use for buffer allocations
- /// The
- public static ResizeKernelMap Calculate(
- IResampler sampler,
+ /// The
+ public static ResizeKernelMap Calculate(
+ in TResampler sampler,
int destinationSize,
int sourceSize,
MemoryAllocator memoryAllocator)
@@ -141,7 +158,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// If we don't have at least 2 periods, we go with the basic implementation:
bool hasAtLeast2Periods = 2 * (cornerInterval + period) < destinationSize;
- ResizeKernelMap result = hasAtLeast2Periods
+ ResizeKernelMap result = hasAtLeast2Periods
? new PeriodicKernelMap(
memoryAllocator,
sampler,
@@ -152,7 +169,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
radius,
period,
cornerInterval)
- : new ResizeKernelMap(
+ : new ResizeKernelMap(
memoryAllocator,
sampler,
sourceSize,
@@ -167,12 +184,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return result;
}
- protected virtual void Initialize()
+ ///
+ /// Initializes the kernel map.
+ ///
+ protected internal virtual void Initialize()
{
for (int i = 0; i < this.DestinationLength; i++)
{
- ResizeKernel kernel = this.BuildKernel(i, i);
- this.kernels[i] = kernel;
+ this.kernels[i] = this.BuildKernel(i, i);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
index ec1f94c143..520370b6ef 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
@@ -21,9 +21,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
(Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options);
this.Sampler = options.Sampler;
- this.TargetWidth = size.Width;
- this.TargetHeight = size.Height;
- this.TargetRectangle = rectangle;
+ this.DestinationWidth = size.Width;
+ this.DestinationHeight = size.Height;
+ this.DestinationRectangle = rectangle;
this.Compand = options.Compand;
}
@@ -33,19 +33,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
public IResampler Sampler { get; }
///
- /// Gets the target width.
+ /// Gets the destination width.
///
- public int TargetWidth { get; }
+ public int DestinationWidth { get; }
///
- /// Gets the target height.
+ /// Gets the destination height.
///
- public int TargetHeight { get; }
+ public int DestinationHeight { get; }
///
/// Gets the resize rectangle.
///
- public Rectangle TargetRectangle { get; }
+ public Rectangle DestinationRectangle { get; }
///
/// Gets a value indicating whether to compress or expand individual pixel color values on processing.
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
index 92c1b71fe1..72064d0e36 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
@@ -1,10 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
@@ -12,59 +8,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// Implements resizing of images using various resamplers.
///
- ///
- /// The original code has been adapted from .
- ///
/// The pixel format.
internal class ResizeProcessor : TransformProcessor
where TPixel : struct, IPixel
{
- private bool isDisposed;
- private readonly int targetWidth;
- private readonly int targetHeight;
+ private readonly int destinationWidth;
+ private readonly int destinationHeight;
private readonly IResampler resampler;
- private readonly Rectangle targetRectangle;
+ private readonly Rectangle destinationRectangle;
private readonly bool compand;
- // The following fields are not immutable but are optionally created on demand.
- private ResizeKernelMap horizontalKernelMap;
- private ResizeKernelMap verticalKernelMap;
-
public ResizeProcessor(Configuration configuration, ResizeProcessor definition, Image source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
- this.targetWidth = definition.TargetWidth;
- this.targetHeight = definition.TargetHeight;
- this.targetRectangle = definition.TargetRectangle;
+ this.destinationWidth = definition.DestinationWidth;
+ this.destinationHeight = definition.DestinationHeight;
+ this.destinationRectangle = definition.DestinationRectangle;
this.resampler = definition.Sampler;
this.compand = definition.Compand;
}
///
- protected override Size GetTargetSize() => new Size(this.targetWidth, this.targetHeight);
+ protected override Size GetDestinationSize() => new Size(this.destinationWidth, this.destinationHeight);
///
protected override void BeforeImageApply(Image destination)
{
- if (!(this.resampler is NearestNeighborResampler))
- {
- Image source = this.Source;
- Rectangle sourceRectangle = this.SourceRectangle;
-
- // Since all image frame dimensions have to be the same we can calculate this for all frames.
- MemoryAllocator memoryAllocator = source.GetMemoryAllocator();
- this.horizontalKernelMap = ResizeKernelMap.Calculate(
- this.resampler,
- this.targetRectangle.Width,
- sourceRectangle.Width,
- memoryAllocator);
-
- this.verticalKernelMap = ResizeKernelMap.Calculate(
- this.resampler,
- this.targetRectangle.Height,
- sourceRectangle.Height,
- memoryAllocator);
- }
+ this.resampler.ApplyResizeTransform(
+ this.Configuration,
+ this.Source,
+ destination,
+ this.SourceRectangle,
+ this.destinationRectangle,
+ this.compand);
base.BeforeImageApply(destination);
}
@@ -72,131 +48,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
protected override void OnFrameApply(ImageFrame source, ImageFrame destination)
{
- Rectangle sourceRectangle = this.SourceRectangle;
- Configuration configuration = this.Configuration;
-
- // Handle resize dimensions identical to the original
- if (source.Width == destination.Width
- && source.Height == destination.Height
- && sourceRectangle == this.targetRectangle)
- {
- // The cloned will be blank here copy all the pixel data over
- source.GetPixelMemoryGroup().CopyTo(destination.GetPixelMemoryGroup());
- return;
- }
-
- int width = this.targetWidth;
- int height = this.targetHeight;
- var interest = Rectangle.Intersect(this.targetRectangle, new Rectangle(0, 0, width, height));
-
- if (this.resampler is NearestNeighborResampler)
- {
- // Scaling factors
- float widthFactor = sourceRectangle.Width / (float)this.targetRectangle.Width;
- float heightFactor = sourceRectangle.Height / (float)this.targetRectangle.Height;
-
- var operation = new RowIntervalOperation(sourceRectangle, this.targetRectangle, widthFactor, heightFactor, source, destination);
- ParallelRowIterator.IterateRows(
- configuration,
- interest,
- in operation);
-
- return;
- }
-
- PixelConversionModifiers conversionModifiers =
- PixelConversionModifiers.Premultiply.ApplyCompanding(this.compand);
-
- BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle);
-
- // To reintroduce parallel processing, we to launch multiple workers
- // for different row intervals of the image.
- using (var worker = new ResizeWorker(
- configuration,
- sourceArea,
- conversionModifiers,
- this.horizontalKernelMap,
- this.verticalKernelMap,
- width,
- interest,
- this.targetRectangle.Location))
- {
- worker.Initialize();
-
- var workingInterval = new RowInterval(interest.Top, interest.Bottom);
- worker.FillDestinationPixels(workingInterval, destination.PixelBuffer);
- }
- }
-
- ///
- protected override void Dispose(bool disposing)
- {
- if (this.isDisposed)
- {
- return;
- }
-
- if (disposing)
- {
- this.horizontalKernelMap?.Dispose();
- this.horizontalKernelMap = null;
- this.verticalKernelMap?.Dispose();
- this.verticalKernelMap = null;
- }
-
- this.isDisposed = true;
- base.Dispose(disposing);
- }
-
- private readonly struct RowIntervalOperation : IRowIntervalOperation
- {
- private readonly Rectangle sourceBounds;
- private readonly Rectangle destinationBounds;
- private readonly float widthFactor;
- private readonly float heightFactor;
- private readonly ImageFrame source;
- private readonly ImageFrame destination;
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
- Rectangle sourceBounds,
- Rectangle destinationBounds,
- float widthFactor,
- float heightFactor,
- ImageFrame source,
- ImageFrame destination)
- {
- this.sourceBounds = sourceBounds;
- this.destinationBounds = destinationBounds;
- this.widthFactor = widthFactor;
- this.heightFactor = heightFactor;
- this.source = source;
- this.destination = destination;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
- {
- int sourceX = this.sourceBounds.X;
- int sourceY = this.sourceBounds.Y;
- int destX = this.destinationBounds.X;
- int destY = this.destinationBounds.Y;
- int destLeft = this.destinationBounds.Left;
- int destRight = this.destinationBounds.Right;
-
- for (int y = rows.Min; y < rows.Max; y++)
- {
- // Y coordinates of source points
- Span sourceRow = this.source.GetPixelRowSpan((int)(((y - destY) * this.heightFactor) + sourceY));
- Span targetRow = this.destination.GetPixelRowSpan(y);
-
- for (int x = destLeft; x < destRight; x++)
- {
- // X coordinates of source points
- targetRow[x] = sourceRow[(int)(((x - destX) * this.widthFactor) + sourceX)];
- }
- }
- }
+ // Everything happens in BeforeImageApply.
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
index de339823e7..cbec5242c0 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
@@ -19,7 +19,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// When sliding the window, the contents of the bottom window band are copied to the new top band.
/// For more details, and visual explanation, see "ResizeWorker.pptx".
///
- internal sealed class ResizeWorker : IDisposable
+ internal sealed class ResizeWorker : IDisposable
+ where TResampler : unmanaged, IResampler
where TPixel : struct, IPixel
{
private readonly Buffer2D transposedFirstPassBuffer;
@@ -28,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly PixelConversionModifiers conversionModifiers;
- private readonly ResizeKernelMap horizontalKernelMap;
+ private readonly ResizeKernelMap horizontalKernelMap;
private readonly BufferArea source;
@@ -38,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly IMemoryOwner tempColumnBuffer;
- private readonly ResizeKernelMap verticalKernelMap;
+ private readonly ResizeKernelMap verticalKernelMap;
private readonly int destWidth;
@@ -56,8 +57,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Configuration configuration,
BufferArea source,
PixelConversionModifiers conversionModifiers,
- ResizeKernelMap horizontalKernelMap,
- ResizeKernelMap verticalKernelMap,
+ ResizeKernelMap horizontalKernelMap,
+ ResizeKernelMap verticalKernelMap,
int destWidth,
Rectangle targetWorkingRect,
Point targetOrigin)
@@ -104,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.tempColumnBuffer.Dispose();
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Span GetColumnSpan(int x, int startY)
{
return this.transposedFirstPassBuffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min);
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs
index beb7ebc9c3..d6fa075366 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs
@@ -13,7 +13,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
///
/// Simplified reference implementation for functionality.
///
- internal class ReferenceKernelMap
+ internal class ReferenceKernelMap
+ where TResampler : unmanaged, IResampler
{
private readonly ReferenceKernel[] kernels;
@@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
public ReferenceKernel GetKernel(int destinationIndex) => this.kernels[destinationIndex];
- public static ReferenceKernelMap Calculate(IResampler sampler, int destinationSize, int sourceSize, bool normalize = true)
+ public static ReferenceKernelMap Calculate(TResampler sampler, int destinationSize, int sourceSize, bool normalize = true)
{
double ratio = (double)sourceSize / destinationSize;
double scale = ratio;
@@ -84,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
result.Add(new ReferenceKernel(left, floatVals));
}
- return new ReferenceKernelMap(result.ToArray());
+ return new ReferenceKernelMap(result.ToArray());
}
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs
index 08745d5701..6ca3c3bee3 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs
@@ -25,59 +25,60 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
///
/// resamplerName, srcSize, destSize
///
- public static readonly TheoryData KernelMapData = new TheoryData
+ public static readonly TheoryData KernelMapData
+ = new TheoryData
{
- { nameof(KnownResamplers.Bicubic), 15, 10 },
- { nameof(KnownResamplers.Bicubic), 10, 15 },
- { nameof(KnownResamplers.Bicubic), 20, 20 },
- { nameof(KnownResamplers.Bicubic), 50, 40 },
- { nameof(KnownResamplers.Bicubic), 40, 50 },
- { nameof(KnownResamplers.Bicubic), 500, 200 },
- { nameof(KnownResamplers.Bicubic), 200, 500 },
- { nameof(KnownResamplers.Bicubic), 3032, 400 },
- { nameof(KnownResamplers.Bicubic), 10, 25 },
- { nameof(KnownResamplers.Lanczos3), 16, 12 },
- { nameof(KnownResamplers.Lanczos3), 12, 16 },
- { nameof(KnownResamplers.Lanczos3), 12, 9 },
- { nameof(KnownResamplers.Lanczos3), 9, 12 },
- { nameof(KnownResamplers.Lanczos3), 6, 8 },
- { nameof(KnownResamplers.Lanczos3), 8, 6 },
- { nameof(KnownResamplers.Lanczos3), 20, 12 },
- { nameof(KnownResamplers.Lanczos3), 5, 25 },
- { nameof(KnownResamplers.Lanczos3), 5, 50 },
- { nameof(KnownResamplers.Lanczos3), 25, 5 },
- { nameof(KnownResamplers.Lanczos3), 50, 5 },
- { nameof(KnownResamplers.Lanczos3), 49, 5 },
- { nameof(KnownResamplers.Lanczos3), 31, 5 },
- { nameof(KnownResamplers.Lanczos8), 500, 200 },
- { nameof(KnownResamplers.Lanczos8), 100, 10 },
- { nameof(KnownResamplers.Lanczos8), 100, 80 },
- { nameof(KnownResamplers.Lanczos8), 10, 100 },
+ { KnownResamplers.Bicubic, 15, 10 },
+ { KnownResamplers.Bicubic, 10, 15 },
+ { KnownResamplers.Bicubic, 20, 20 },
+ { KnownResamplers.Bicubic, 50, 40 },
+ { KnownResamplers.Bicubic, 40, 50 },
+ { KnownResamplers.Bicubic, 500, 200 },
+ { KnownResamplers.Bicubic, 200, 500 },
+ { KnownResamplers.Bicubic, 3032, 400 },
+ { KnownResamplers.Bicubic, 10, 25 },
+ { KnownResamplers.Lanczos3, 16, 12 },
+ { KnownResamplers.Lanczos3, 12, 16 },
+ { KnownResamplers.Lanczos3, 12, 9 },
+ { KnownResamplers.Lanczos3, 9, 12 },
+ { KnownResamplers.Lanczos3, 6, 8 },
+ { KnownResamplers.Lanczos3, 8, 6 },
+ { KnownResamplers.Lanczos3, 20, 12 },
+ { KnownResamplers.Lanczos3, 5, 25 },
+ { KnownResamplers.Lanczos3, 5, 50 },
+ { KnownResamplers.Lanczos3, 25, 5 },
+ { KnownResamplers.Lanczos3, 50, 5 },
+ { KnownResamplers.Lanczos3, 49, 5 },
+ { KnownResamplers.Lanczos3, 31, 5 },
+ { KnownResamplers.Lanczos8, 500, 200 },
+ { KnownResamplers.Lanczos8, 100, 10 },
+ { KnownResamplers.Lanczos8, 100, 80 },
+ { KnownResamplers.Lanczos8, 10, 100 },
// Resize_WorksWithAllResamplers_Rgba32_CalliphoraPartial_Box-0.5:
- { nameof(KnownResamplers.Box), 378, 149 },
- { nameof(KnownResamplers.Box), 349, 174 },
+ { KnownResamplers.Box, 378, 149 },
+ { KnownResamplers.Box, 349, 174 },
// Accuracy-related regression-test cases cherry-picked from GeneratedImageResizeData
- { nameof(KnownResamplers.Box), 201, 100 },
- { nameof(KnownResamplers.Box), 199, 99 },
- { nameof(KnownResamplers.Box), 10, 299 },
- { nameof(KnownResamplers.Box), 299, 10 },
- { nameof(KnownResamplers.Box), 301, 300 },
- { nameof(KnownResamplers.Box), 1180, 480 },
- { nameof(KnownResamplers.Lanczos2), 3264, 3032 },
- { nameof(KnownResamplers.Bicubic), 1280, 2240 },
- { nameof(KnownResamplers.Bicubic), 1920, 1680 },
- { nameof(KnownResamplers.Bicubic), 3072, 2240 },
- { nameof(KnownResamplers.Welch), 300, 2008 },
+ { KnownResamplers.Box, 201, 100 },
+ { KnownResamplers.Box, 199, 99 },
+ { KnownResamplers.Box, 10, 299 },
+ { KnownResamplers.Box, 299, 10 },
+ { KnownResamplers.Box, 301, 300 },
+ { KnownResamplers.Box, 1180, 480 },
+ { KnownResamplers.Lanczos2, 3264, 3032 },
+ { KnownResamplers.Bicubic, 1280, 2240 },
+ { KnownResamplers.Bicubic, 1920, 1680 },
+ { KnownResamplers.Bicubic, 3072, 2240 },
+ { KnownResamplers.Welch, 300, 2008 },
// ResizeKernel.Length -related regression tests cherry-picked from GeneratedImageResizeData
- { nameof(KnownResamplers.Bicubic), 10, 50 },
- { nameof(KnownResamplers.Bicubic), 49, 301 },
- { nameof(KnownResamplers.Bicubic), 301, 49 },
- { nameof(KnownResamplers.Bicubic), 1680, 1200 },
- { nameof(KnownResamplers.Box), 13, 299 },
- { nameof(KnownResamplers.Lanczos5), 3032, 600 },
+ { KnownResamplers.Bicubic, 10, 50 },
+ { KnownResamplers.Bicubic, 49, 301 },
+ { KnownResamplers.Bicubic, 301, 49 },
+ { KnownResamplers.Bicubic, 1680, 1200 },
+ { KnownResamplers.Box, 13, 299 },
+ { KnownResamplers.Lanczos5, 3032, 600 },
};
public static TheoryData GeneratedImageResizeData =
@@ -85,20 +86,20 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
[Theory(Skip = "Only for debugging and development")]
[MemberData(nameof(KernelMapData))]
- public void PrintNonNormalizedKernelMap(string resamplerName, int srcSize, int destSize)
+ public void PrintNonNormalizedKernelMap(TResampler resampler, int srcSize, int destSize)
+ where TResampler : unmanaged, IResampler
{
- IResampler resampler = TestUtils.GetResampler(resamplerName);
-
- var kernelMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize, false);
+ var kernelMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize, false);
this.Output.WriteLine($"Actual KernelMap:\n{PrintKernelMap(kernelMap)}\n");
}
[Theory]
[MemberData(nameof(KernelMapData))]
- public void KernelMapContentIsCorrect(string resamplerName, int srcSize, int destSize)
+ public void KernelMapContentIsCorrect(TResampler resampler, int srcSize, int destSize)
+ where TResampler : unmanaged, IResampler
{
- this.VerifyKernelMapContentIsCorrect(resamplerName, srcSize, destSize);
+ this.VerifyKernelMapContentIsCorrect(resampler, srcSize, destSize);
}
// Comprehensive but expensive tests, for ResizeKernelMap.
@@ -113,12 +114,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
}
#endif
- private void VerifyKernelMapContentIsCorrect(string resamplerName, int srcSize, int destSize)
+ private void VerifyKernelMapContentIsCorrect(TResampler resampler, int srcSize, int destSize)
+ where TResampler : unmanaged, IResampler
{
- IResampler resampler = TestUtils.GetResampler(resamplerName);
-
- var referenceMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize);
- var kernelMap = ResizeKernelMap.Calculate(resampler, destSize, srcSize, Configuration.Default.MemoryAllocator);
+ var referenceMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize);
+ var kernelMap = ResizeKernelMap.Calculate(resampler, destSize, srcSize, Configuration.Default.MemoryAllocator);
#if DEBUG
this.Output.WriteLine(kernelMap.Info);
@@ -153,20 +153,23 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
}
}
- private static string PrintKernelMap(ResizeKernelMap kernelMap) =>
- PrintKernelMap(kernelMap, km => km.DestinationLength, (km, i) => km.GetKernel(i));
+ private static string PrintKernelMap(ResizeKernelMap kernelMap)
+ where TResampler : unmanaged, IResampler
+ => PrintKernelMap>(kernelMap, km => km.DestinationLength, (km, i) => km.GetKernel(i));
- private static string PrintKernelMap(ReferenceKernelMap kernelMap) =>
- PrintKernelMap(kernelMap, km => km.DestinationSize, (km, i) => km.GetKernel(i));
+ private static string PrintKernelMap(ReferenceKernelMap kernelMap)
+ where TResampler : unmanaged, IResampler
+ => PrintKernelMap>(kernelMap, km => km.DestinationSize, (km, i) => km.GetKernel(i));
- private static string PrintKernelMap(
+ private static string PrintKernelMap(
TKernelMap kernelMap,
Func getDestinationSize,
Func getKernel)
+ where TResampler : unmanaged, IResampler
{
var bld = new StringBuilder();
- if (kernelMap is ResizeKernelMap actualMap)
+ if (kernelMap is ResizeKernelMap actualMap)
{
bld.AppendLine(actualMap.Info);
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
index 2cbffef47f..63c93596fb 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
@@ -121,8 +121,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
configuration.MemoryAllocator = allocator;
configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInBytes;
- var verticalKernelMap = ResizeKernelMap.Calculate(
- KnownResamplers.Bicubic,
+ var verticalKernelMap = ResizeKernelMap.Calculate(
+ default,
destSize.Height,
image0.Height,
Configuration.Default.MemoryAllocator);
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs
index 33da33c717..db1e76ae5d 100644
--- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs
+++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Processing;
@@ -20,9 +20,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
this.operations.Pad(width, height);
ResizeProcessor resizeProcessor = this.Verify();
- Assert.Equal(width, resizeProcessor.TargetWidth);
- Assert.Equal(height, resizeProcessor.TargetHeight);
+ Assert.Equal(width, resizeProcessor.DestinationWidth);
+ Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs
index f87e17e060..e7b92b7b32 100644
--- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs
@@ -17,8 +17,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
this.operations.Resize(width, height);
ResizeProcessor resizeProcessor = this.Verify();
- Assert.Equal(width, resizeProcessor.TargetWidth);
- Assert.Equal(height, resizeProcessor.TargetHeight);
+ Assert.Equal(width, resizeProcessor.DestinationWidth);
+ Assert.Equal(height, resizeProcessor.DestinationHeight);
}
[Fact]
@@ -30,8 +30,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
this.operations.Resize(width, height, sampler);
ResizeProcessor resizeProcessor = this.Verify();
- Assert.Equal(width, resizeProcessor.TargetWidth);
- Assert.Equal(height, resizeProcessor.TargetHeight);
+ Assert.Equal(width, resizeProcessor.DestinationWidth);
+ Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
}
@@ -47,8 +47,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
this.operations.Resize(width, height, sampler, compand);
ResizeProcessor resizeProcessor = this.Verify();
- Assert.Equal(width, resizeProcessor.TargetWidth);
- Assert.Equal(height, resizeProcessor.TargetHeight);
+ Assert.Equal(width, resizeProcessor.DestinationWidth);
+ Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(compand, resizeProcessor.Compand);
}
@@ -73,8 +73,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
this.operations.Resize(resizeOptions);
ResizeProcessor resizeProcessor = this.Verify();
- Assert.Equal(width, resizeProcessor.TargetWidth);
- Assert.Equal(height, resizeProcessor.TargetHeight);
+ Assert.Equal(width, resizeProcessor.DestinationWidth);
+ Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(compand, resizeProcessor.Compand);