From 626aef8c20cd8eee402ba141823d4ced1a219ecc Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Wed, 22 Jun 2016 21:40:05 +0200 Subject: [PATCH 1/9] Removed first pass Former-commit-id: ae4c65acb9d7eb7b5d2840b6a268ee8483d226b1 Former-commit-id: ac8bb1c013bf432f990487d01b3e797578ce29b0 Former-commit-id: 9965e32b231efe13d189ecb6d6f594d9809b6d93 --- NuGet.config | 2 +- .../Samplers/Processors/SkewProcessor.cs | 83 ++++++++++--------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/NuGet.config b/NuGet.config index 554c2f634..18aee5e9d 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,4 +1,4 @@ - + diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 1bfcfb7e2..d7498d286 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -3,6 +3,8 @@ // Licensed under the Apache License, Version 2.0. // +using System; + namespace ImageProcessorCore { using System.Numerics; @@ -13,11 +15,7 @@ namespace ImageProcessorCore /// public class SkewProcessor : ImageSampler { - /// - /// The image used for storing the first pass pixels. - /// - private Image firstPass; - + /// /// The angle of rotation along the x-axis. /// @@ -112,53 +110,60 @@ namespace ImageProcessorCore // Get the padded bounds and resize the image. Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); - this.firstPass = new Image(rectangle.Width, rectangle.Height); - target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); - new ResizeProcessor(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); - } - else - { - // Just clone the pixels across. - this.firstPass = new Image(source.Width, source.Height); - this.firstPass.ClonePixels(source.Width, source.Height, source.Pixels); + target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); } } /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { - int height = this.firstPass.Height; - int startX = 0; - int endX = this.firstPass.Width; - Point centre = this.Center == Point.Empty ? Rectangle.Center(this.firstPass.Bounds) : this.Center; - Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); - - // Since we are not working in parallel we use full height and width - // of the first pass image. - Parallel.For( - 0, - height, - y => + + int skewMaxX = target.Width - source.Width; + int skewMaxY = target.Height - source.Height; + + int[] deltaX = new int[source.Height]; + for (int i = 0; i < deltaX.Length; i++) + { + deltaX[i] = GetSkewDelta(i, angleX); + if (angleX < 0) { - for (int x = startX; x < endX; x++) - { - // Skew at the centre point - Point skewed = Point.Skew(new Point(x, y), skew); - if (this.firstPass.Bounds.Contains(skewed.X, skewed.Y)) - { - target[x, y] = this.firstPass[skewed.X, skewed.Y]; - } - } - - this.OnRowProcessed(); - }); + deltaX[i] += skewMaxX; + } + } + + + Parallel.For( + 0, + source.Width, + sx => + { + int deltaY = GetSkewDelta(sx, angleY); + if (AngleY < 0) + { + deltaY += skewMaxY; + } + for (int sy = 0; sy < source.Height; sy++) + { + target[deltaX[sy] + sx, deltaY + sy] = source[sx, sy]; + } + this.OnRowProcessed(); + }); } + private int GetSkewDelta(int sy, float angle) + { + float radians = ImageMaths.DegreesToRadians(angle); + double delta = Math.Tan(radians); + delta = delta * sy; + return ((int)delta); + } + + + /// protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) { // Cleanup. - this.firstPass.Dispose(); } } } \ No newline at end of file From 8bb74abd4791c461a0dfe094ed95a420aaab0f8c Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Thu, 23 Jun 2016 01:00:31 +0200 Subject: [PATCH 2/9] found stepping bug Former-commit-id: ee2d54efce687030938c51f5886331974183cbd4 Former-commit-id: 8c080d5a56232ce06304afecb56ac339dd677689 Former-commit-id: 06bb22b1b2c9f757a52194a79641eb56d9d747aa --- .../Samplers/Processors/SkewProcessor.cs | 70 ++++++------------- .../Processors/Samplers/SamplerTests.cs | 2 +- 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index d7498d286..766907361 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -15,7 +15,6 @@ namespace ImageProcessorCore /// public class SkewProcessor : ImageSampler { - /// /// The angle of rotation along the x-axis. /// @@ -41,16 +40,6 @@ namespace ImageProcessorCore set { - if (value > 360) - { - value -= 360; - } - - if (value < 0) - { - value += 360; - } - this.angleX = value; } } @@ -67,16 +56,6 @@ namespace ImageProcessorCore set { - if (value > 360) - { - value -= 360; - } - - if (value < 0) - { - value += 360; - } - this.angleY = value; } } @@ -110,54 +89,51 @@ namespace ImageProcessorCore // Get the padded bounds and resize the image. Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); - target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); + target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); } } /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { - int skewMaxX = target.Width - source.Width; int skewMaxY = target.Height - source.Height; + int offesetX = 0; + int offesetY = 0; - int[] deltaX = new int[source.Height]; - for (int i = 0; i < deltaX.Length; i++) + if (ImageMaths.DegreesToRadians(angleX) < 0) { - deltaX[i] = GetSkewDelta(i, angleX); - if (angleX < 0) - { - deltaX[i] += skewMaxX; - } + offesetX = skewMaxX; + skewMaxX = -skewMaxX; + } + if (ImageMaths.DegreesToRadians(angleY) < 0) + { + offesetY = skewMaxY; + // skewMaxY = -skewMaxY; + + } + + Parallel.For( 0, - source.Width, - sx => + source.Height, + sy => { - int deltaY = GetSkewDelta(sx, angleY); - if (AngleY < 0) - { - deltaY += skewMaxY; - } - for (int sy = 0; sy < source.Height; sy++) + + for (int sx = 0; sx < source.Width; sx++) { - target[deltaX[sy] + sx, deltaY + sy] = source[sx, sy]; + int skewY = ((skewMaxX * (sy)) / (source.Height - 1)) + offesetX; + int skewX = ((skewMaxY * (sx-source.Width-1)) / (source.Width - 1))+ offesetY; + target[skewY + sx, sy +skewX ] = source[sx, sy]; } this.OnRowProcessed(); }); - } - private int GetSkewDelta(int sy, float angle) - { - float radians = ImageMaths.DegreesToRadians(angle); - double delta = Math.Tan(radians); - delta = delta * sy; - return ((int)delta); - } + } /// diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index ac610746e..c529e94d9 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(20, 10, this.ProgressUpdate) + image.Skew(5, -2, this.ProgressUpdate) .Save(output); } From 6147ca03d9eef7df6f2e237c2cd8d82c3db6bf64 Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Thu, 23 Jun 2016 19:59:31 +0200 Subject: [PATCH 3/9] a smal bug Former-commit-id: c6e0afbd230747057de8314c9599821c69dc1ffe Former-commit-id: be47dfa7a12de85db15a8c00ac434952213fafbb Former-commit-id: 891a14bf95046a3a8eb5108c6e389060a01a5094 --- .../Samplers/Processors/SkewProcessor.cs | 67 ++++++++++--------- .../Processors/Samplers/SamplerTests.cs | 2 +- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 766907361..c50e7ccc5 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -98,41 +98,42 @@ namespace ImageProcessorCore { int skewMaxX = target.Width - source.Width; int skewMaxY = target.Height - source.Height; - int offesetX = 0; - int offesetY = 0; - - if (ImageMaths.DegreesToRadians(angleX) < 0) - { - offesetX = skewMaxX; - skewMaxX = -skewMaxX; - - } - if (ImageMaths.DegreesToRadians(angleY) < 0) - { - offesetY = skewMaxY; - // skewMaxY = -skewMaxY; - - } - - - + bool revX = ImageMaths.DegreesToRadians(angleX) < 0; + bool revY = ImageMaths.DegreesToRadians(angleY) < 0; Parallel.For( - 0, - source.Height, - sy => - { - - for (int sx = 0; sx < source.Width; sx++) - { - int skewY = ((skewMaxX * (sy)) / (source.Height - 1)) + offesetX; - int skewX = ((skewMaxY * (sx-source.Width-1)) / (source.Width - 1))+ offesetY; - target[skewY + sx, sy +skewX ] = source[sx, sy]; - } - this.OnRowProcessed(); - }); - - + 0, + source.Height, + sy => + { + int deltaX; + if (revX) + { + deltaX = ((skewMaxX * (-sy + (source.Height - 1))) / (source.Height - 1)); + } + else + { + deltaX = (((skewMaxX * sy)) / (source.Height - 1)); + } + + for (int sx = 0; sx < source.Width; sx++) + { + int deltaY; + if (revY) + { + deltaY = ((((skewMaxY * -sx ))+ (skewMaxY-1)) -(skewMaxY-1)) / (source.Width - 1) + skewMaxY; + //deltaY = (((skewMaxY * sx)) / (source.Height - 1)); + // deltaY = -deltaY + skewMaxY; + //deltaY = 0; + } + else + { + deltaY = ((skewMaxY * sx) / (source.Width - 1)); + } + target[deltaX + sx, sy + deltaY] = source[sx, sy]; + } + this.OnRowProcessed(); + }); } diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index c529e94d9..b628049aa 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(5, -2, this.ProgressUpdate) + image.Skew(10, -20, this.ProgressUpdate) .Save(output); } From 288fe6ecfcf89d175b2c5de1c31ebe2b4fdf563d Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Thu, 23 Jun 2016 22:55:57 +0200 Subject: [PATCH 4/9] allmost Former-commit-id: 2381cad96fed8bc6fcdf302ae430902ab5e49250 Former-commit-id: 85b9f55b31c5d2e664cf86ac08696e2929de1b05 Former-commit-id: cfbb14402f0dbb5bf915b67af8778c00a7f18e98 --- .../Samplers/Processors/SkewProcessor.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index c50e7ccc5..8b373de75 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -116,21 +116,22 @@ namespace ImageProcessorCore deltaX = (((skewMaxX * sy)) / (source.Height - 1)); } + for (int sx = 0; sx < source.Width; sx++) { int deltaY; if (revY) { - deltaY = ((((skewMaxY * -sx ))+ (skewMaxY-1)) -(skewMaxY-1)) / (source.Width - 1) + skewMaxY; + deltaY = ((((-skewMaxY*(sx + deltaX)))/(source.Width-skewMaxX - 1)))+skewMaxY; //deltaY = (((skewMaxY * sx)) / (source.Height - 1)); - // deltaY = -deltaY + skewMaxY; - //deltaY = 0; + // deltaY = -deltaY + skewMaxY; + // deltaY = sx+deltaX; } else { deltaY = ((skewMaxY * sx) / (source.Width - 1)); } - target[deltaX + sx, sy + deltaY] = source[sx, sy]; + target[deltaX + sx, Math.Abs(sy + deltaY)%(target.Height-1)] = source[sx, sy]; } this.OnRowProcessed(); }); From 53fbb7d0bb1a4bba747a264e0a9a011ae35cc430 Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Thu, 23 Jun 2016 22:59:47 +0200 Subject: [PATCH 5/9] how needs float or double Former-commit-id: 4636317442582ed070b7e5b60a1c1671ee04fe49 Former-commit-id: b9cfab5bc32cd78a1f3c6ea65b3eb3026214dc66 Former-commit-id: 0cd0ab47777a3a93bb5a4edb0b9cd644b7311d55 --- src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 8b373de75..da08d0bc0 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -116,13 +116,13 @@ namespace ImageProcessorCore deltaX = (((skewMaxX * sy)) / (source.Height - 1)); } - + int off = (skewMaxY*skewMaxX)/(source.Width - skewMaxX - 1); for (int sx = 0; sx < source.Width; sx++) { int deltaY; if (revY) { - deltaY = ((((-skewMaxY*(sx + deltaX)))/(source.Width-skewMaxX - 1)))+skewMaxY; + deltaY = ((((-skewMaxY*(sx + deltaX)))/(source.Width-skewMaxX - 1)))+skewMaxY+off; //deltaY = (((skewMaxY * sx)) / (source.Height - 1)); // deltaY = -deltaY + skewMaxY; // deltaY = sx+deltaX; From 10dabe43bf52410feb079cc784a1fb86874089ef Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Thu, 23 Jun 2016 23:11:25 +0200 Subject: [PATCH 6/9] 50 degree problem Former-commit-id: 0520faa2f766ec02358fce15ec7207dc3f05a2fa Former-commit-id: d09c6d305cb917e513a2f0a85a7e236bb115e7a2 Former-commit-id: f3d80d94646b8ab67d41168ef35cdcb4dd3e2359 --- src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs | 4 +--- .../Processors/Samplers/SamplerTests.cs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index da08d0bc0..eb3fac8ca 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -123,9 +123,7 @@ namespace ImageProcessorCore if (revY) { deltaY = ((((-skewMaxY*(sx + deltaX)))/(source.Width-skewMaxX - 1)))+skewMaxY+off; - //deltaY = (((skewMaxY * sx)) / (source.Height - 1)); - // deltaY = -deltaY + skewMaxY; - // deltaY = sx+deltaX; + } else { diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index b628049aa..874258544 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(10, -20, this.ProgressUpdate) + image.Skew(50, -60, this.ProgressUpdate) .Save(output); } From d1c73acb9160efc20f633bf0e58855898537decd Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Sun, 26 Jun 2016 14:52:51 +0200 Subject: [PATCH 7/9] I suspect that resize is aslo worng Former-commit-id: 02a07dbd5b84292e2b5fea6c4dd164d323a9a4cf Former-commit-id: a45041a6f7cf0b1eb6ba88ed68545e4375cf6890 Former-commit-id: 3ab6536cddbc2e09b20ce54b1334ca1f3e5aca88 --- .../Samplers/Processors/SkewProcessor.cs | 103 +++++++++++------- .../Processors/Samplers/SamplerTests.cs | 2 +- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index eb3fac8ca..3aa1e6d6c 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -15,6 +15,11 @@ namespace ImageProcessorCore /// public class SkewProcessor : ImageSampler { + /// + /// The image used for storing the first pass pixels. + /// + // private Image firstPass; + /// /// The angle of rotation along the x-axis. /// @@ -40,6 +45,16 @@ namespace ImageProcessorCore set { + if (value > 360) + { + value -= 360; + } + + if (value < 0) + { + value += 360; + } + this.angleX = value; } } @@ -56,6 +71,16 @@ namespace ImageProcessorCore set { + if (value > 360) + { + value -= 360; + } + + if (value < 0) + { + value += 360; + } + this.angleY = value; } } @@ -89,57 +114,61 @@ namespace ImageProcessorCore // Get the padded bounds and resize the image. Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); + // this.firstPass = new Image(rectangle.Width, rectangle.Height); target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); + // new ResizeProcessor(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); + } + else + { + // Just clone the pixels across. + // this.firstPass = new Image(source.Width, source.Height); + // this.firstPass.ClonePixels(source.Width, source.Height, source.Pixels); } } /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { - int skewMaxX = target.Width - source.Width; - int skewMaxY = target.Height - source.Height; - - bool revX = ImageMaths.DegreesToRadians(angleX) < 0; - bool revY = ImageMaths.DegreesToRadians(angleY) < 0; + int height = target.Height; + int startX = 0; + int endX = target.Width; + Point centre = Rectangle.Center(source.Bounds); + Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); + + // Since we are not working in parallel we use full height and width + // of the first pass image. Parallel.For( - 0, - source.Height, - sy => - { - int deltaX; - if (revX) - { - deltaX = ((skewMaxX * (-sy + (source.Height - 1))) / (source.Height - 1)); - } - else - { - deltaX = (((skewMaxX * sy)) / (source.Height - 1)); - } - - int off = (skewMaxY*skewMaxX)/(source.Width - skewMaxX - 1); - for (int sx = 0; sx < source.Width; sx++) - { - int deltaY; - if (revY) - { - deltaY = ((((-skewMaxY*(sx + deltaX)))/(source.Width-skewMaxX - 1)))+skewMaxY+off; - - } - else - { - deltaY = ((skewMaxY * sx) / (source.Width - 1)); - } - target[deltaX + sx, Math.Abs(sy + deltaY)%(target.Height-1)] = source[sx, sy]; - } - this.OnRowProcessed(); - }); + 0, + height, + y => + { + for (int x = startX; x < endX; x++) + { + // Skew at the centre point + Point skewed = Point.Skew(new Point(x, y), skew); + if (source.Bounds.Contains(skewed.X, skewed.Y)) + { + target[x, y] = source[skewed.X, skewed.Y]; + } + else + { + Color c= source[Math.Abs(skewed.X%(source.Width-1)), Math.Abs(skewed.Y % (source.Height - 1))]; + c.B = 0; + c.G = 0; + target[x, y]=c; + } + + } + + this.OnRowProcessed(); + }); } - /// protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) { // Cleanup. + // this.firstPass.Dispose(); } } } \ No newline at end of file diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index 874258544..104b885a9 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(50, -60, this.ProgressUpdate) + image.Skew(45, 0, this.ProgressUpdate) .Save(output); } From 00546c2f1c7e580faf25f4a408f5b2779ec46390 Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Sun, 26 Jun 2016 18:16:34 +0200 Subject: [PATCH 8/9] Mad code simple as pssible Former-commit-id: a54d5643736150d029ae1fbdbf8866de0ed9cc19 Former-commit-id: 35ff5d480c7082b92b37d1ebeda1b88a57a9235f Former-commit-id: d1872fb301e23d0fdbbe085223ed8838bcc8ef63 --- .../Common/Helpers/ImageMaths.cs | 4 +- .../Samplers/Processors/SkewProcessor.cs | 44 ++++--------------- .../Processors/Samplers/SamplerTests.cs | 2 +- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/src/ImageProcessorCore/Common/Helpers/ImageMaths.cs b/src/ImageProcessorCore/Common/Helpers/ImageMaths.cs index c85499081..3658bdf3a 100644 --- a/src/ImageProcessorCore/Common/Helpers/ImageMaths.cs +++ b/src/ImageProcessorCore/Common/Helpers/ImageMaths.cs @@ -148,8 +148,8 @@ namespace ImageProcessorCore Vector2 rightBottom = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Bottom), matrix); Vector2[] allCorners = { leftTop, rightTop, leftBottom, rightBottom }; - float extentX = allCorners.Select(v => v.X).Max() - allCorners.Select(v => v.X).Min(); - float extentY = allCorners.Select(v => v.Y).Max() - allCorners.Select(v => v.Y).Min(); + float extentX = allCorners.Select(v => v.X).Max()- allCorners.Select(v => v.X).Min(); + float extentY = allCorners.Select(v => v.Y).Max()- allCorners.Select(v => v.Y).Min(); return new Rectangle(0, 0, (int)extentX, (int)extentY); } diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 3aa1e6d6c..a5f5b3122 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -4,6 +4,7 @@ // using System; +using System.Linq; namespace ImageProcessorCore { @@ -98,31 +99,12 @@ namespace ImageProcessorCore /// protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) { - // If we are expanding we need to pad the bounds of the source rectangle. - // We can use the resizer in nearest neighbor mode to do this fairly quickly. if (this.Expand) { - // First find out how big the target rectangle should be. - Point centre = this.Center == Point.Empty ? Rectangle.Center(sourceRectangle) : this.Center; - Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); - Rectangle rectangle = ImageMaths.GetBoundingRectangle(sourceRectangle, skew); - ResizeOptions options = new ResizeOptions - { - Size = new Size(rectangle.Width, rectangle.Height), - Mode = ResizeMode.BoxPad - }; - - // Get the padded bounds and resize the image. - Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); - // this.firstPass = new Image(rectangle.Width, rectangle.Height); - target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); - // new ResizeProcessor(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); - } - else - { - // Just clone the pixels across. - // this.firstPass = new Image(source.Width, source.Height); - // this.firstPass.ClonePixels(source.Width, source.Height, source.Pixels); + Point centre = new Point(0,0); + Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -angleY); + Rectangle rect = ImageMaths.GetBoundingRectangle(source.Bounds, skew); + target.SetPixels(rect.Width, rect.Height, new float[rect.Width*rect.Height*4]); } } @@ -132,11 +114,9 @@ namespace ImageProcessorCore int height = target.Height; int startX = 0; int endX = target.Width; - Point centre = Rectangle.Center(source.Bounds); + Point centre; + centre = new Point(0,0); Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); - - // Since we are not working in parallel we use full height and width - // of the first pass image. Parallel.For( 0, height, @@ -144,14 +124,15 @@ namespace ImageProcessorCore { for (int x = startX; x < endX; x++) { - // Skew at the centre point Point skewed = Point.Skew(new Point(x, y), skew); if (source.Bounds.Contains(skewed.X, skewed.Y)) { target[x, y] = source[skewed.X, skewed.Y]; } + else { + // just for debugging. Color c= source[Math.Abs(skewed.X%(source.Width-1)), Math.Abs(skewed.Y % (source.Height - 1))]; c.B = 0; c.G = 0; @@ -159,16 +140,9 @@ namespace ImageProcessorCore } } - this.OnRowProcessed(); }); } - /// - protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) - { - // Cleanup. - // this.firstPass.Dispose(); - } } } \ No newline at end of file diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index 104b885a9..506a2274b 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(45, 0, this.ProgressUpdate) + image.Skew(15, 12, this.ProgressUpdate) .Save(output); } From 3ab4c9311a2eeae24cabd7c6eff79421d98e612e Mon Sep 17 00:00:00 2001 From: Sverre Rekvin Date: Mon, 27 Jun 2016 03:20:26 +0200 Subject: [PATCH 9/9] Inv matrix, traget size of image was wrong Former-commit-id: b62be965af469e6c365f57261b5790ac05475329 Former-commit-id: 621c23abc663803c7b49e81ce3e576a2042dc740 Former-commit-id: e133d3a733742ec6038f8fb9f2053731e6f44618 --- .../Samplers/Processors/SkewProcessor.cs | 55 ++++++++----------- .../Processors/Samplers/SamplerTests.cs | 2 +- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index a5f5b3122..119aa37ed 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -46,15 +46,6 @@ namespace ImageProcessorCore set { - if (value > 360) - { - value -= 360; - } - - if (value < 0) - { - value += 360; - } this.angleX = value; } @@ -72,15 +63,7 @@ namespace ImageProcessorCore set { - if (value > 360) - { - value -= 360; - } - if (value < 0) - { - value += 360; - } this.angleY = value; } @@ -101,10 +84,12 @@ namespace ImageProcessorCore { if (this.Expand) { - Point centre = new Point(0,0); + Point centre = new Point(0, 0); Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -angleY); - Rectangle rect = ImageMaths.GetBoundingRectangle(source.Bounds, skew); - target.SetPixels(rect.Width, rect.Height, new float[rect.Width*rect.Height*4]); + Matrix3x2 invSkew; + Matrix3x2.Invert(skew, out invSkew); + Rectangle rect = ImageMaths.GetBoundingRectangle(source.Bounds, invSkew); + target.SetPixels(rect.Width, rect.Height, new float[rect.Width * rect.Height * 4]); } } @@ -114,9 +99,23 @@ namespace ImageProcessorCore int height = target.Height; int startX = 0; int endX = target.Width; - Point centre; - centre = new Point(0,0); - Matrix3x2 skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); + Point centre = new Point(0, 0); + + Matrix3x2 invSkew = new Matrix3x2(); + var skew = Point.CreateSkew(centre, -this.angleX, -this.angleY); + Matrix3x2.Invert(skew, out invSkew); + + Vector2 rightTop = Vector2.Transform(new Vector2(source.Width, 0), invSkew); + Vector2 leftBottom = Vector2.Transform(new Vector2(0, source.Height), invSkew); + + + if (angleX < 0 && AngleY > 0) + skew = Point.CreateSkew(new Point((int)-leftBottom.X, (int)leftBottom.Y), -this.angleX, -this.angleY); + if (angleX > 0 && AngleY < 0) + skew = Point.CreateSkew(new Point((int)rightTop.X, (int)-rightTop.Y), -this.angleX, -this.angleY); + if (angleX < 0 && AngleY < 0) + skew = Point.CreateSkew(new Point(target.Width-1, target.Height-1), -this.angleX, -this.angleY); + Parallel.For( 0, height, @@ -129,16 +128,6 @@ namespace ImageProcessorCore { target[x, y] = source[skewed.X, skewed.Y]; } - - else - { - // just for debugging. - Color c= source[Math.Abs(skewed.X%(source.Width-1)), Math.Abs(skewed.Y % (source.Height - 1))]; - c.B = 0; - c.G = 0; - target[x, y]=c; - } - } this.OnRowProcessed(); }); diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index 506a2274b..2f85dd3e5 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -500,7 +500,7 @@ using (Image image = new Image(stream)) using (FileStream output = File.OpenWrite($"TestOutput/Skew/{filename}")) { - image.Skew(15, 12, this.ProgressUpdate) + image.Skew(-15, 12, this.ProgressUpdate) .Save(output); }