From 219fdbd36bdc9042739f0175596a5513df1877a8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 23 Jan 2018 16:31:28 +1100 Subject: [PATCH] Use premultiply for resize. Fix #428 --- .../Processors/Transforms/AffineTransformProcessor.cs | 4 ++-- .../Transforms/ProjectiveTransformProcessor.cs | 4 ++-- .../Processing/Processors/Transforms/WeightsWindow.cs | 8 ++++---- .../Processors/Convolution/DetectEdgesTest.cs | 11 +++-------- .../Processing/Processors/Transforms/ResizeTests.cs | 2 +- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs index 07c247d734..9d7056b67d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs @@ -204,7 +204,7 @@ namespace SixLabors.ImageSharp.Processing.Processors var vector = source[i, j].ToVector4(); // Values are first premultiplied to prevent darkening of edge pixels - var mupltiplied = new Vector4(new Vector3(vector.X, vector.Y, vector.Z) * vector.W, vector.W); + Vector4 mupltiplied = vector.Premultiply(); sum += mupltiplied * xWeight * yWeight; } } @@ -212,7 +212,7 @@ namespace SixLabors.ImageSharp.Processing.Processors ref TPixel dest = ref destRow[x]; // Reverse the premultiplication - dest.PackFromVector4(new Vector4(new Vector3(sum.X, sum.Y, sum.Z) / sum.W, sum.W)); + dest.PackFromVector4(sum.UnPremultiply()); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index f53585093b..463d3717d0 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -199,7 +199,7 @@ namespace SixLabors.ImageSharp.Processing.Processors var vector = source[i, j].ToVector4(); // Values are first premultiplied to prevent darkening of edge pixels - var mupltiplied = new Vector4(new Vector3(vector.X, vector.Y, vector.Z) * vector.W, vector.W); + Vector4 mupltiplied = vector.Premultiply(); sum += mupltiplied * xWeight * yWeight; } } @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors ref TPixel dest = ref destRow[x]; // Reverse the premultiplication - dest.PackFromVector4(new Vector4(new Vector3(sum.X, sum.Y, sum.Z) / sum.W, sum.W)); + dest.PackFromVector4(sum.UnPremultiply()); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs index d23ee5a060..b0a530514e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Processing.Processors { float weight = Unsafe.Add(ref horizontalValues, i); Vector4 v = Unsafe.Add(ref vecPtr, i); - result += v * weight; + result += v.Premultiply() * weight; } return result; @@ -114,10 +114,10 @@ namespace SixLabors.ImageSharp.Processing.Processors { float weight = Unsafe.Add(ref horizontalValues, i); Vector4 v = Unsafe.Add(ref vecPtr, i); - result += v.Expand() * weight; + result += v.Premultiply().Expand() * weight; } - return result; + return result.UnPremultiply(); } /// @@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.Processing.Processors result += firstPassPixels[x, index] * yw; } - return result; + return result.UnPremultiply(); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index c2d8916384..1b678f20bc 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution public class DetectEdgesTest : FileTestBase { public static readonly string[] CommonTestImages = { TestImages.Png.Bike }; - + public static readonly TheoryData DetectEdgesFilters = new TheoryData { EdgeDetection.Kayyali, @@ -54,9 +54,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { image.Mutate(x => x.DetectEdges()); image.DebugSave(provider); - - // TODO: Enable once we have updated the images - // image.CompareToReferenceOutput(provider); + image.CompareToReferenceOutput(provider); } } @@ -85,10 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution image.DebugSave(provider); // TODO: Enable once we have updated the images - //image.CompareToReferenceOutput(provider); - - // TODO: We don't need this any longer after switching to ReferenceImages - //ImageComparer.Tolerant().EnsureProcessorChangesAreConstrained(source, image, bounds); + image.CompareToReferenceOutput(provider); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 92f1af58ed..72febea340 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, true)); + image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.NearestNeighbor)); // Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :( image.DebugSave(provider, extension: Extensions.Gif);