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); }