diff --git a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs index 213ab1b4a..47763c0aa 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. @@ -73,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); @@ -84,9 +84,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 +97,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(targetX, width); this.blender.Blend(background, background, foreground, amount); }); } diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index 94dd903b4..2e3a730fc 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,49 @@ namespace SixLabors.ImageSharp.Tests image.DebugSave(provider, new { mode }); } } + + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] + public void ImageShouldHandleNegativeLocation(TestImageProvider provider) + { + 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(Rgba32.White, backgroundPixel); + Assert.Equal(overlayPixel, background[0, 0]); + + background.DebugSave(provider, new[] { "Negative" }); + } + } + + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] + public void ImageShouldHandlePositiveLocation(TestImageProvider provider) + { + 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(Rgba32.White, backgroundPixel); + Assert.Equal(overlayPixel, background[xy, xy]); + + background.DebugSave(provider, new[] { "Positive" }); + } + } } }