diff --git a/src/ImageSharp/Formats/Webp/IWebpEncoderOptions.cs b/src/ImageSharp/Formats/Webp/IWebpEncoderOptions.cs
index 000de4f88..d119d3031 100644
--- a/src/ImageSharp/Formats/Webp/IWebpEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Webp/IWebpEncoderOptions.cs
@@ -10,6 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
{
///
/// Gets the webp file format used. Either lossless or lossy.
+ /// Defaults to lossy.
///
WebpFileFormatType? FileFormat { get; }
diff --git a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs
index 8640261b1..195fa62bd 100644
--- a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs
@@ -70,6 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
///
/// Indicating what file format compression should be used.
+ /// Defaults to lossy.
///
private readonly WebpFileFormatType? fileFormat;
@@ -112,43 +113,43 @@ namespace SixLabors.ImageSharp.Formats.Webp
Guard.NotNull(stream, nameof(stream));
this.configuration = image.GetConfiguration();
- bool lossy;
+ bool lossless;
if (this.fileFormat is not null)
{
- lossy = this.fileFormat == WebpFileFormatType.Lossy;
+ lossless = this.fileFormat == WebpFileFormatType.Lossless;
}
else
{
WebpMetadata webpMetadata = image.Metadata.GetWebpMetadata();
- lossy = webpMetadata.FileFormat == WebpFileFormatType.Lossy;
+ lossless = webpMetadata.FileFormat == WebpFileFormatType.Lossless;
}
- if (lossy)
+ if (lossless)
{
- using var enc = new Vp8Encoder(
+ using var enc = new Vp8LEncoder(
this.memoryAllocator,
this.configuration,
image.Width,
image.Height,
this.quality,
this.method,
- this.entropyPasses,
- this.filterStrength,
- this.spatialNoiseShaping);
+ this.transparentColorMode,
+ this.nearLossless,
+ this.nearLosslessQuality);
enc.Encode(image, stream);
}
else
{
- using var enc = new Vp8LEncoder(
+ using var enc = new Vp8Encoder(
this.memoryAllocator,
this.configuration,
image.Width,
image.Height,
this.quality,
this.method,
- this.transparentColorMode,
- this.nearLossless,
- this.nearLosslessQuality);
+ this.entropyPasses,
+ this.filterStrength,
+ this.spatialNoiseShaping);
enc.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Memory/Buffer2DRegion{T}.cs b/src/ImageSharp/Memory/Buffer2DRegion{T}.cs
index d1c39ccbf..13b339597 100644
--- a/src/ImageSharp/Memory/Buffer2DRegion{T}.cs
+++ b/src/ImageSharp/Memory/Buffer2DRegion{T}.cs
@@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Memory
/// The row index
/// The span
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Span GetRowSpan(int y)
+ public Span DangerousGetRowSpan(int y)
{
int yy = this.Rectangle.Y + y;
int xx = this.Rectangle.X;
@@ -152,7 +152,7 @@ namespace SixLabors.ImageSharp.Memory
for (int y = 0; y < this.Rectangle.Height; y++)
{
- Span row = this.GetRowSpan(y);
+ Span row = this.DangerousGetRowSpan(y);
row.Clear();
}
}
diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
index 2a41329a6..3e420ca03 100644
--- a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
@@ -46,38 +46,25 @@ namespace SixLabors.ImageSharp.Processing.Processors
///
Image ICloningImageProcessor.CloneAndExecute()
{
- try
- {
- Image clone = this.CreateTarget();
- this.CheckFrameCount(this.Source, clone);
+ Image clone = this.CreateTarget();
+ this.CheckFrameCount(this.Source, clone);
- Configuration configuration = this.Configuration;
- this.BeforeImageApply(clone);
+ Configuration configuration = this.Configuration;
+ this.BeforeImageApply(clone);
- for (int i = 0; i < this.Source.Frames.Count; i++)
- {
- ImageFrame sourceFrame = this.Source.Frames[i];
- ImageFrame clonedFrame = clone.Frames[i];
+ for (int i = 0; i < this.Source.Frames.Count; i++)
+ {
+ ImageFrame sourceFrame = this.Source.Frames[i];
+ ImageFrame clonedFrame = clone.Frames[i];
- this.BeforeFrameApply(sourceFrame, clonedFrame);
- this.OnFrameApply(sourceFrame, clonedFrame);
- this.AfterFrameApply(sourceFrame, clonedFrame);
- }
+ this.BeforeFrameApply(sourceFrame, clonedFrame);
+ this.OnFrameApply(sourceFrame, clonedFrame);
+ this.AfterFrameApply(sourceFrame, clonedFrame);
+ }
- this.AfterImageApply(clone);
+ this.AfterImageApply(clone);
- return clone;
- }
-#if DEBUG
- catch (Exception)
- {
- throw;
-#else
- catch (Exception ex)
- {
- throw new ImageProcessingException($"An error occurred when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex);
-#endif
- }
+ return clone;
}
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor.cs
index 77ba9582d..75f82a25a 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor.cs
@@ -21,6 +21,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Guard.NotNull(sampler, nameof(sampler));
Guard.MustBeValueType(sampler, nameof(sampler));
+ if (TransformUtils.IsDegenerate(matrix))
+ {
+ throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
+ }
+
this.Sampler = sampler;
this.TransformMatrix = matrix;
this.DestinationSize = targetDimensions;
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
index 640527fe7..f6fadca33 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
@@ -61,10 +61,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Matrix3x2 matrix = this.transformMatrix;
// Handle transforms that result in output identical to the original.
- if (matrix.Equals(default) || matrix.Equals(Matrix3x2.Identity))
+ // Degenerate matrices are already handled in the upstream definition.
+ if (matrix.Equals(Matrix3x2.Identity))
{
// The clone will be blank here copy all the pixel data over
- source.GetPixelMemoryGroup().CopyTo(destination.GetPixelMemoryGroup());
+ var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
+ Buffer2DRegion sourceBuffer = source.PixelBuffer.GetRegion(interest);
+ Buffer2DRegion destbuffer = destination.PixelBuffer.GetRegion(interest);
+ for (int y = 0; y < sourceBuffer.Height; y++)
+ {
+ sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y));
+ }
+
return;
}
@@ -73,7 +81,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (sampler is NearestNeighborResampler)
{
- var nnOperation = new NNAffineOperation(source.PixelBuffer, destination.PixelBuffer, matrix);
+ var nnOperation = new NNAffineOperation(
+ source.PixelBuffer,
+ Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
+ destination.PixelBuffer,
+ matrix);
+
ParallelRowIterator.IterateRows(
configuration,
destination.Bounds(),
@@ -85,6 +98,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
var operation = new AffineOperation(
configuration,
source.PixelBuffer,
+ Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
destination.PixelBuffer,
in sampler,
matrix);
@@ -105,12 +119,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(InliningOptions.ShortMethod)]
public NNAffineOperation(
Buffer2D source,
+ Rectangle bounds,
Buffer2D destination,
Matrix3x2 matrix)
{
this.source = source;
+ this.bounds = bounds;
this.destination = destination;
- this.bounds = source.Bounds();
this.matrix = matrix;
}
@@ -138,6 +153,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
private readonly Configuration configuration;
private readonly Buffer2D source;
+ private readonly Rectangle bounds;
private readonly Buffer2D destination;
private readonly TResampler sampler;
private readonly Matrix3x2 matrix;
@@ -148,12 +164,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
public AffineOperation(
Configuration configuration,
Buffer2D source,
+ Rectangle bounds,
Buffer2D destination,
in TResampler sampler,
Matrix3x2 matrix)
{
this.configuration = configuration;
this.source = source;
+ this.bounds = bounds;
this.destination = destination;
this.sampler = sampler;
this.matrix = matrix;
@@ -182,8 +200,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
TResampler sampler = this.sampler;
float yRadius = this.yRadius;
float xRadius = this.xRadius;
- int maxY = this.source.Height - 1;
- int maxX = this.source.Width - 1;
+ int minY = this.bounds.Y;
+ int maxY = this.bounds.Bottom - 1;
+ int minX = this.bounds.X;
+ int maxX = this.bounds.Right - 1;
for (int y = rows.Min; y < rows.Max; y++)
{
@@ -200,10 +220,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float pY = point.Y;
float pX = point.X;
- int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY);
- int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY);
- int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX);
- int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX);
+ int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY);
+ int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY);
+ int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX);
+ int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX);
if (bottom == top || right == left)
{
@@ -245,8 +265,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
TResampler sampler = this.sampler;
float yRadius = this.yRadius;
float xRadius = this.xRadius;
- int maxY = this.source.Height - 1;
- int maxX = this.source.Width - 1;
+ int minY = this.bounds.Y;
+ int maxY = this.bounds.Bottom - 1;
+ int minX = this.bounds.X;
+ int maxX = this.bounds.Right - 1;
for (int y = rows.Min; y < rows.Max; y++)
{
@@ -263,10 +285,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float pY = point.Y;
float pX = point.X;
- int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY);
- int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY);
- int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX);
- int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX);
+ int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY);
+ int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY);
+ int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX);
+ int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX);
if (bottom == top || right == left)
{
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs
index c6168b461..fd0c7f23b 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs
@@ -39,11 +39,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// The radius.
/// The center position.
+ /// The min allowed amouunt.
/// The max allowed amouunt.
/// The .
[MethodImpl(InliningOptions.ShortMethod)]
- public static int GetRangeStart(float radius, float center, int max)
- => Numerics.Clamp((int)MathF.Ceiling(center - radius), 0, max);
+ public static int GetRangeStart(float radius, float center, int min, int max)
+ => Numerics.Clamp((int)MathF.Ceiling(center - radius), min, max);
///
/// Gets the end position (inclusive) for a sampling range given
@@ -51,10 +52,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// The radius.
/// The center position.
+ /// The min allowed amouunt.
/// The max allowed amouunt.
/// The .
[MethodImpl(InliningOptions.ShortMethod)]
- public static int GetRangeEnd(float radius, float center, int max)
- => Numerics.Clamp((int)MathF.Floor(center + radius), 0, max);
+ public static int GetRangeEnd(float radius, float center, int min, int max)
+ => Numerics.Clamp((int)MathF.Floor(center + radius), min, max);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs
index 338489d3f..5eb89fe8a 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs
@@ -21,6 +21,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Guard.NotNull(sampler, nameof(sampler));
Guard.MustBeValueType(sampler, nameof(sampler));
+ if (TransformUtils.IsDegenerate(matrix))
+ {
+ throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
+ }
+
this.Sampler = sampler;
this.TransformMatrix = matrix;
this.DestinationSize = targetDimensions;
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
index cf6567629..26b970d8b 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
@@ -60,10 +60,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Matrix4x4 matrix = this.transformMatrix;
// Handle transforms that result in output identical to the original.
- if (matrix.Equals(default) || matrix.Equals(Matrix4x4.Identity))
+ // Degenerate matrices are already handled in the upstream definition.
+ if (matrix.Equals(Matrix4x4.Identity))
{
// The clone will be blank here copy all the pixel data over
- source.GetPixelMemoryGroup().CopyTo(destination.GetPixelMemoryGroup());
+ var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
+ Buffer2DRegion sourceBuffer = source.PixelBuffer.GetRegion(interest);
+ Buffer2DRegion destbuffer = destination.PixelBuffer.GetRegion(interest);
+ for (int y = 0; y < sourceBuffer.Height; y++)
+ {
+ sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y));
+ }
+
return;
}
@@ -72,7 +80,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (sampler is NearestNeighborResampler)
{
- var nnOperation = new NNProjectiveOperation(source.PixelBuffer, destination.PixelBuffer, matrix);
+ var nnOperation = new NNProjectiveOperation(
+ source.PixelBuffer,
+ Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
+ destination.PixelBuffer,
+ matrix);
+
ParallelRowIterator.IterateRows(
configuration,
destination.Bounds(),
@@ -84,6 +97,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
var operation = new ProjectiveOperation(
configuration,
source.PixelBuffer,
+ Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
destination.PixelBuffer,
in sampler,
matrix);
@@ -104,12 +118,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(InliningOptions.ShortMethod)]
public NNProjectiveOperation(
Buffer2D source,
+ Rectangle bounds,
Buffer2D destination,
Matrix4x4 matrix)
{
this.source = source;
+ this.bounds = bounds;
this.destination = destination;
- this.bounds = source.Bounds();
this.matrix = matrix;
}
@@ -137,6 +152,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
private readonly Configuration configuration;
private readonly Buffer2D source;
+ private readonly Rectangle bounds;
private readonly Buffer2D destination;
private readonly TResampler sampler;
private readonly Matrix4x4 matrix;
@@ -147,18 +163,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
public ProjectiveOperation(
Configuration configuration,
Buffer2D source,
+ Rectangle bounds,
Buffer2D destination,
in TResampler sampler,
Matrix4x4 matrix)
{
this.configuration = configuration;
this.source = source;
+ this.bounds = bounds;
this.destination = destination;
this.sampler = sampler;
this.matrix = matrix;
- this.yRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Height, destination.Height);
- this.xRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Width, destination.Width);
+ this.yRadius = LinearTransformUtility.GetSamplingRadius(in sampler, bounds.Height, destination.Height);
+ this.xRadius = LinearTransformUtility.GetSamplingRadius(in sampler, bounds.Width, destination.Width);
}
[MethodImpl(InliningOptions.ShortMethod)]
@@ -181,8 +199,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
TResampler sampler = this.sampler;
float yRadius = this.yRadius;
float xRadius = this.xRadius;
- int maxY = this.source.Height - 1;
- int maxX = this.source.Width - 1;
+ int minY = this.bounds.Y;
+ int maxY = this.bounds.Bottom - 1;
+ int minX = this.bounds.X;
+ int maxX = this.bounds.Right - 1;
for (int y = rows.Min; y < rows.Max; y++)
{
@@ -199,10 +219,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float pY = point.Y;
float pX = point.X;
- int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY);
- int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY);
- int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX);
- int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX);
+ int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY);
+ int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY);
+ int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX);
+ int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX);
if (bottom <= top || right <= left)
{
@@ -244,8 +264,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
TResampler sampler = this.sampler;
float yRadius = this.yRadius;
float xRadius = this.xRadius;
- int maxY = this.source.Height - 1;
- int maxX = this.source.Width - 1;
+ int minY = this.bounds.Y;
+ int maxY = this.bounds.Bottom - 1;
+ int minX = this.bounds.X;
+ int maxX = this.bounds.Right - 1;
for (int y = rows.Min; y < rows.Max; y++)
{
@@ -262,10 +284,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float pY = point.Y;
float pX = point.X;
- int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY);
- int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY);
- int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX);
- int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX);
+ int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY);
+ int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY);
+ int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX);
+ int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX);
if (bottom <= top || right <= left)
{
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
index 93aeb75f4..90cbf8bda 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
@@ -172,7 +172,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int y = calculationInterval.Min; y < calculationInterval.Max; y++)
{
- Span sourceRow = this.source.GetRowSpan(y);
+ Span sourceRow = this.source.DangerousGetRowSpan(y);
PixelOperations.Instance.ToVector4(
this.configuration,
diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
index cad39224e..7043549b2 100644
--- a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
private static string TestImageLossyFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, Lossy.NoFilter06);
[Theory]
- [WithFile(Flag, PixelTypes.Rgba32, WebpFileFormatType.Lossless)] // if its not a webp input image, it should default to lossless.
+ [WithFile(Flag, PixelTypes.Rgba32, WebpFileFormatType.Lossy)] // If its not a webp input image, it should default to lossy.
[WithFile(Lossless.NoTransform1, PixelTypes.Rgba32, WebpFileFormatType.Lossless)]
[WithFile(Lossy.Bike, PixelTypes.Rgba32, WebpFileFormatType.Lossy)]
public void Encode_PreserveRatio(TestImageProvider provider, WebpFileFormatType expectedFormat)
diff --git a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.cs
index 00acce64e..4ab2c93a5 100644
--- a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.cs
+++ b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.cs
@@ -245,43 +245,45 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators
cleanup.Register(b1);
}
- public static readonly bool IsNotMacOS = !TestEnvironment.IsOSX;
-
- // TODO: Investigate MacOS failures
- [ConditionalTheory(nameof(IsNotMacOS))]
+ [Theory]
[InlineData(false)]
[InlineData(true)]
public void RentReturnRelease_SubsequentRentReturnsDifferentHandles(bool multiple)
{
- var pool = new UniformUnmanagedMemoryPool(16, 16);
- using var cleanup = new CleanupUtil(pool);
- UnmanagedMemoryHandle b0 = pool.Rent();
- IntPtr h0 = b0.Handle;
- UnmanagedMemoryHandle b1 = pool.Rent();
- IntPtr h1 = b1.Handle;
- pool.Return(b0);
- pool.Return(b1);
- pool.Release();
-
- // Do some unmanaged allocations to make sure new pool buffers are different:
- IntPtr[] dummy = Enumerable.Range(0, 100).Select(_ => Marshal.AllocHGlobal(16)).ToArray();
- cleanup.Register(dummy);
+ RemoteExecutor.Invoke(RunTest, multiple.ToString()).Dispose();
- if (multiple)
+ static void RunTest(string multipleInner)
{
- UnmanagedMemoryHandle b = pool.Rent();
- cleanup.Register(b);
- Assert.NotEqual(h0, b.Handle);
- Assert.NotEqual(h1, b.Handle);
- }
- else
- {
- UnmanagedMemoryHandle[] b = pool.Rent(2);
- cleanup.Register(b);
- Assert.NotEqual(h0, b[0].Handle);
- Assert.NotEqual(h1, b[0].Handle);
- Assert.NotEqual(h0, b[1].Handle);
- Assert.NotEqual(h1, b[1].Handle);
+ var pool = new UniformUnmanagedMemoryPool(16, 16);
+ using var cleanup = new CleanupUtil(pool);
+ UnmanagedMemoryHandle b0 = pool.Rent();
+ IntPtr h0 = b0.Handle;
+ UnmanagedMemoryHandle b1 = pool.Rent();
+ IntPtr h1 = b1.Handle;
+ pool.Return(b0);
+ pool.Return(b1);
+ pool.Release();
+
+ // Do some unmanaged allocations to make sure new pool buffers are different:
+ IntPtr[] dummy = Enumerable.Range(0, 100).Select(_ => Marshal.AllocHGlobal(16)).ToArray();
+ cleanup.Register(dummy);
+
+ if (bool.Parse(multipleInner))
+ {
+ UnmanagedMemoryHandle b = pool.Rent();
+ cleanup.Register(b);
+ Assert.NotEqual(h0, b.Handle);
+ Assert.NotEqual(h1, b.Handle);
+ }
+ else
+ {
+ UnmanagedMemoryHandle[] b = pool.Rent(2);
+ cleanup.Register(b);
+ Assert.NotEqual(h0, b[0].Handle);
+ Assert.NotEqual(h1, b[0].Handle);
+ Assert.NotEqual(h0, b[1].Handle);
+ Assert.NotEqual(h1, b[1].Handle);
+ }
}
}
diff --git a/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs b/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
index 76e55aa3a..12b7c74ab 100644
--- a/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
+++ b/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
Buffer2DRegion region = buffer.GetRegion(r);
- Span span = region.GetRowSpan(y);
+ Span span = region.DangerousGetRowSpan(y);
Assert.Equal(w, span.Length);
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
index 3cd8cec15..33725f7aa 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
@@ -4,6 +4,7 @@
using System;
using System.Numerics;
using System.Reflection;
+using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
@@ -224,6 +225,46 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
c => c.Transform(builder));
}
+ [Fact]
+ public void Issue1911()
+ {
+ using var image = new Image(100, 100);
+ image.Mutate(x => x = x.Transform(new Rectangle(0, 0, 99, 100), Matrix3x2.Identity, new Size(99, 100), KnownResamplers.Lanczos2));
+
+ Assert.Equal(99, image.Width);
+ Assert.Equal(100, image.Height);
+ }
+
+ [Theory]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32)]
+ public void Identity(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage();
+
+ Matrix3x2 m = Matrix3x2.Identity;
+ Rectangle r = new(25, 25, 50, 50);
+ image.Mutate(x => x.Transform(r, m, new Size(100, 100), KnownResamplers.Bicubic));
+ image.DebugSave(provider);
+ image.CompareToReferenceOutput(ValidatorComparer, provider);
+ }
+
+ [Theory]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 0.0001F)]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 57F)]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 0F)]
+ public void Transform_With_Custom_Dimensions(TestImageProvider provider, float radians)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage();
+
+ var m = Matrix3x2.CreateRotation(radians, new Vector2(50, 50));
+ Rectangle r = new(25, 25, 50, 50);
+ image.Mutate(x => x.Transform(r, m, new Size(100, 100), KnownResamplers.Bicubic));
+ image.DebugSave(provider, testOutputDetails: radians);
+ image.CompareToReferenceOutput(ValidatorComparer, provider, testOutputDetails: radians);
+ }
+
private static IResampler GetResampler(string name)
{
PropertyInfo property = typeof(KnownResamplers).GetTypeInfo().GetProperty(name);
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs
index ef8e03763..d841c963f 100644
--- a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs
@@ -147,6 +147,46 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
}
}
+ [Fact]
+ public void Issue1911()
+ {
+ using var image = new Image(100, 100);
+ image.Mutate(x => x = x.Transform(new Rectangle(0, 0, 99, 100), Matrix4x4.Identity, new Size(99, 100), KnownResamplers.Lanczos2));
+
+ Assert.Equal(99, image.Width);
+ Assert.Equal(100, image.Height);
+ }
+
+ [Theory]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32)]
+ public void Identity(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage();
+
+ Matrix4x4 m = Matrix4x4.Identity;
+ Rectangle r = new(25, 25, 50, 50);
+ image.Mutate(x => x.Transform(r, m, new Size(100, 100), KnownResamplers.Bicubic));
+ image.DebugSave(provider);
+ image.CompareToReferenceOutput(ValidatorComparer, provider);
+ }
+
+ [Theory]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 0.0001F)]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 57F)]
+ [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 0F)]
+ public void Transform_With_Custom_Dimensions(TestImageProvider provider, float radians)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage();
+
+ Matrix4x4 m = Matrix4x4.CreateRotationX(radians, new Vector3(50, 50, 1F)) * Matrix4x4.CreateRotationY(radians, new Vector3(50, 50, 1F));
+ Rectangle r = new(25, 25, 50, 50);
+ image.Mutate(x => x.Transform(r, m, new Size(100, 100), KnownResamplers.Bicubic));
+ image.DebugSave(provider, testOutputDetails: radians);
+ image.CompareToReferenceOutput(ValidatorComparer, provider, testOutputDetails: radians);
+ }
+
private static IResampler GetResampler(string name)
{
PropertyInfo property = typeof(KnownResamplers).GetTypeInfo().GetProperty(name);
diff --git a/tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs b/tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs
index 9a8d8351b..7529b0e5f 100644
--- a/tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs
+++ b/tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
var white = new L8(255);
for (int y = 0; y < region.Height; y++)
{
- region.GetRowSpan(y).Fill(white);
+ region.DangerousGetRowSpan(y).Fill(white);
}
}
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Identity_Rgba32_TestPattern100x100.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Identity_Rgba32_TestPattern100x100.png
new file mode 100644
index 000000000..ce6e8ce9f
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Identity_Rgba32_TestPattern100x100.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:da8229605bda413676a42f587df250a743540e6e00c04eacb1e622f223e19595
+size 3564
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
index f5af01102..53ac0ff89 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b01d54838d678b61c3b7a1c7e76ff9a60b3f5f4faef5af848231177eac956eb1
-size 1262
+oid sha256:bbe1ffaf7b801fd92724438cc810fd0c5506e0a907b970c4f0bf5bec3627ca2a
+size 551
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
index e5005ac5d..2480164d6 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d34394771605c2a70cc23f3841592c20d22a68aaabf2ad6e8aba7348a181afb3
-size 531
+oid sha256:b45933471a1af1b6d4112240e1bc6b6187065a872043ddbf917200ce9e8cc84b
+size 371
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
new file mode 100644
index 000000000..4b9953b67
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dd3b29b530e221618f65cd5e493b21fe3c27804fde7664636b7bb002f72abbb2
+size 3663
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png
new file mode 100644
index 000000000..ce6e8ce9f
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:da8229605bda413676a42f587df250a743540e6e00c04eacb1e622f223e19595
+size 3564
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
new file mode 100644
index 000000000..5f4911e47
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a35757fef08a6fd9b37e719d5be7a82d5ff79f0395e082f697d9ebe9c7f03cc8
+size 5748
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Identity_Rgba32_TestPattern100x100.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Identity_Rgba32_TestPattern100x100.png
new file mode 100644
index 000000000..ce6e8ce9f
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Identity_Rgba32_TestPattern100x100.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:da8229605bda413676a42f587df250a743540e6e00c04eacb1e622f223e19595
+size 3564
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
new file mode 100644
index 000000000..e8efa8a98
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:39c25539c3c9b8926bf65c041df693a60617bbe8653bb72357bde5ab6342c59c
+size 3618
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png
new file mode 100644
index 000000000..ce6e8ce9f
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:da8229605bda413676a42f587df250a743540e6e00c04eacb1e622f223e19595
+size 3564
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
new file mode 100644
index 000000000..99a74e400
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8b1fc95fdf07c7443147205afffb157aa82f94818cfbb833a615c42f584fbda0
+size 5070