From 403b7759df4c30b60517972a6d3eb21473e0cf55 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 8 Oct 2017 13:25:36 +1100 Subject: [PATCH 1/4] Remove PixelAccessor and cleanup --- .../Processors/DrawImageProcessor.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs index 213ab1b4a..a88a0a6d0 100644 --- a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Numerics; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Helpers; @@ -42,7 +41,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors /// /// Gets the image to blend. /// - public Image Image { get; private set; } + public Image Image { get; } /// /// Gets the alpha percentage value. @@ -84,9 +83,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors maxY = Math.Min(this.Location.Y + this.Size.Height, maxY); int width = maxX - minX; - using (Buffer amount = new Buffer(width)) - using (PixelAccessor toBlendPixels = targetImage.Lock()) - using (PixelAccessor sourcePixels = source.Lock()) + using (var amount = new Buffer(width)) { for (int i = 0; i < width; i++) { @@ -99,8 +96,8 @@ namespace SixLabors.ImageSharp.Drawing.Processors configuration.ParallelOptions, y => { - Span background = sourcePixels.GetRowSpan(y).Slice(minX, width); - Span foreground = toBlendPixels.GetRowSpan(y - this.Location.Y).Slice(0, width); + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = targetImage.GetPixelRowSpan(y - this.Location.Y).Slice(0, width); this.blender.Blend(background, background, foreground, amount); }); } From 55d688387ee976f35e620144131c118efc1598ef Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 8 Oct 2017 16:55:29 +1100 Subject: [PATCH 2/4] Correctly handle negative x location. Fix #252 --- src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs index a88a0a6d0..47763c0aa 100644 --- a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs @@ -72,10 +72,11 @@ namespace SixLabors.ImageSharp.Drawing.Processors } // Align start/end positions. - Rectangle bounds = this.Image.Bounds(); + Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); maxX = Math.Min(this.Location.X + this.Size.Width, maxX); + int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); @@ -97,7 +98,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors y => { Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = targetImage.GetPixelRowSpan(y - this.Location.Y).Slice(0, width); + Span foreground = targetImage.GetPixelRowSpan(y - this.Location.Y).Slice(targetX, width); this.blender.Blend(background, background, foreground, amount); }); } From e53618c1f75017cadda2dd380cffe4cb10e2232f Mon Sep 17 00:00:00 2001 From: JimBobSquarePants Date: Mon, 9 Oct 2017 09:48:45 +1100 Subject: [PATCH 3/4] Add missing unit tests --- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index 94dd903b4..53986e6d5 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -9,6 +9,8 @@ using Xunit; namespace SixLabors.ImageSharp.Tests { + using System; + public class DrawImageTest : FileTestBase { private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; @@ -42,5 +44,45 @@ namespace SixLabors.ImageSharp.Tests image.DebugSave(provider, new { mode }); } } + + [Theory] + [WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, TestImages.Png.Splash)] + public void ImageShouldHandleNegativeLocation(TestImageProvider provider, string backgroundPath) + { + using (Image background = TestFile.Create(backgroundPath).CreateImage()) + using (Image overlay = provider.GetImage()) + { + int xy = -25; + Rgba32 backgroundPixel = background[0, 0]; + Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1]; + + background.Mutate(x => x.DrawImage(overlay, PixelBlenderMode.Normal, 1F, new Size(overlay.Width, overlay.Height), new Point(xy, xy))); + + Assert.Equal(default(Rgba32), backgroundPixel); + Assert.Equal(overlayPixel, background[0, 0]); + + background.DebugSave(provider, new[] { "Negative" }); + } + } + + [Theory] + [WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, TestImages.Png.Splash)] + public void ImageShouldHandlePositiveLocation(TestImageProvider provider, string backgroundPath) + { + using (Image background = TestFile.Create(backgroundPath).CreateImage()) + using (Image overlay = provider.GetImage()) + { + int xy = 25; + Rgba32 backgroundPixel = background[xy - 1, xy - 1]; + Rgba32 overlayPixel = overlay[0, 0]; + + background.Mutate(x => x.DrawImage(overlay, PixelBlenderMode.Normal, 1F, new Size(overlay.Width, overlay.Height), new Point(xy, xy))); + + Assert.Equal(default(Rgba32), backgroundPixel); + Assert.Equal(overlayPixel, background[xy, xy]); + + background.DebugSave(provider, new[] { "Positive" }); + } + } } } From ab1dc518b4dbfbc234f4546d05df19771752c876 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 9 Oct 2017 20:55:41 +1100 Subject: [PATCH 4/4] More lightweight tests --- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index 53986e6d5..2e3a730fc 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -46,19 +46,21 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, TestImages.Png.Splash)] - public void ImageShouldHandleNegativeLocation(TestImageProvider provider, string backgroundPath) + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] + public void ImageShouldHandleNegativeLocation(TestImageProvider provider) { - using (Image background = TestFile.Create(backgroundPath).CreateImage()) - using (Image overlay = provider.GetImage()) + using (Image background = provider.GetImage()) + using (var overlay = new Image(50, 50)) { + overlay.Mutate(x => x.Fill(Rgba32.Black)); + int xy = -25; Rgba32 backgroundPixel = background[0, 0]; Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1]; background.Mutate(x => x.DrawImage(overlay, PixelBlenderMode.Normal, 1F, new Size(overlay.Width, overlay.Height), new Point(xy, xy))); - Assert.Equal(default(Rgba32), backgroundPixel); + Assert.Equal(Rgba32.White, backgroundPixel); Assert.Equal(overlayPixel, background[0, 0]); background.DebugSave(provider, new[] { "Negative" }); @@ -66,19 +68,21 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, TestImages.Png.Splash)] - public void ImageShouldHandlePositiveLocation(TestImageProvider provider, string backgroundPath) + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] + public void ImageShouldHandlePositiveLocation(TestImageProvider provider) { - using (Image background = TestFile.Create(backgroundPath).CreateImage()) - using (Image overlay = provider.GetImage()) + using (Image background = provider.GetImage()) + using (var overlay = new Image(50, 50)) { + overlay.Mutate(x => x.Fill(Rgba32.Black)); + int xy = 25; Rgba32 backgroundPixel = background[xy - 1, xy - 1]; Rgba32 overlayPixel = overlay[0, 0]; background.Mutate(x => x.DrawImage(overlay, PixelBlenderMode.Normal, 1F, new Size(overlay.Width, overlay.Height), new Point(xy, xy))); - Assert.Equal(default(Rgba32), backgroundPixel); + Assert.Equal(Rgba32.White, backgroundPixel); Assert.Equal(overlayPixel, background[xy, xy]); background.DebugSave(provider, new[] { "Positive" });