diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs
index 47826411..5d8075e3 100644
--- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs
+++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs
@@ -24,7 +24,7 @@ public class ImageBrush : Brush
///
/// Initializes a new instance of the class.
///
- /// The image.
+ /// The source image to draw.
public ImageBrush(Image image)
: this(image, image.Bounds)
{
@@ -33,15 +33,12 @@ public ImageBrush(Image image)
///
/// Initializes a new instance of the class.
///
- /// The image.
- ///
- /// The region of interest.
- /// This overrides any region used to initialize the brush applicator.
- ///
- internal ImageBrush(Image image, RectangleF region)
+ /// The source image.
+ /// The region of interest within the source image to draw.
+ public ImageBrush(Image image, RectangleF region)
{
this.image = image;
- this.region = region;
+ this.region = RectangleF.Intersect(image.Bounds, region);
}
///
diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillImageBrushTests.cs
index 62f27ffd..ec2e3e6a 100644
--- a/tests/ImageSharp.Drawing.Tests/Drawing/FillImageBrushTests.cs
+++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillImageBrushTests.cs
@@ -14,10 +14,10 @@ public class FillImageBrushTests
[Fact]
public void DoesNotDisposeImage()
{
- using (var src = new Image(5, 5))
+ using (Image src = new(5, 5))
{
- var brush = new ImageBrush(src);
- using (var dest = new Image(10, 10))
+ ImageBrush brush = new(src);
+ using (Image dest = new(10, 10))
{
dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10)));
dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10)));
@@ -36,7 +36,7 @@ public void UseBrushOfDifferentPixelType(TestImageProvider provi
? Image.Load(data)
: Image.Load(data);
- var brush = new ImageBrush(overlay);
+ ImageBrush brush = new(overlay);
background.Mutate(c => c.Fill(brush));
background.DebugSave(provider, appendSourceFileOrDescription: false);
@@ -54,7 +54,7 @@ public void CanDrawLandscapeImage(TestImageProvider provider)
overlay.Mutate(c => c.Crop(new Rectangle(0, 0, 125, 90)));
- var brush = new ImageBrush(overlay);
+ ImageBrush brush = new(overlay);
background.Mutate(c => c.Fill(brush));
background.DebugSave(provider, appendSourceFileOrDescription: false);
@@ -72,10 +72,61 @@ public void CanDrawPortraitImage(TestImageProvider provider)
overlay.Mutate(c => c.Crop(new Rectangle(0, 0, 90, 125)));
- var brush = new ImageBrush(overlay);
+ ImageBrush brush = new(overlay);
background.Mutate(c => c.Fill(brush));
background.DebugSave(provider, appendSourceFileOrDescription: false);
background.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false);
}
+
+ [Theory]
+ [WithSolidFilledImages(1000, 1000, "White", PixelTypes.Rgba32)]
+ public void CanDrawNegativeOffsetImage(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ byte[] data = TestFile.Create(TestImages.Png.Ducky).Bytes;
+ using Image background = provider.GetImage();
+ using Image overlay = Image.Load(data);
+
+ overlay.Mutate(c => c.Resize(100, 100));
+
+ ImageBrush halfBrush = new(overlay, new RectangleF(50, 0, 50, 100));
+ ImageBrush fullBrush = new(overlay);
+ background.Mutate(c => DrawFull(c, new Size(100, 100), fullBrush, halfBrush, background.Width, background.Height));
+
+ background.DebugSave(provider, appendSourceFileOrDescription: false);
+ background.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false);
+ }
+
+ private static void DrawFull(IImageProcessingContext ctx, Size size, ImageBrush brush, ImageBrush halfBrush, int width, int height)
+ {
+ int j = 0;
+ while (j < height)
+ {
+ bool half = false;
+ int limitWidth = width;
+ int i = 0;
+ if ((j / size.Height) % 2 != 0)
+ {
+ half = true;
+ }
+
+ while (i < limitWidth)
+ {
+ if (half)
+ {
+ ctx.Fill(halfBrush, new RectangleF(i, j, size.Width / 2f, size.Height));
+ i += (int)(size.Width / 2f);
+ half = false;
+ }
+ else
+ {
+ ctx.Fill(brush, new RectangleF(new PointF(i, j), size));
+ i += size.Width;
+ }
+ }
+
+ j += size.Height;
+ }
+ }
}
diff --git a/tests/Images/ReferenceOutput/Drawing/FillImageBrushTests/CanDrawNegativeOffsetImage_Rgba32.png b/tests/Images/ReferenceOutput/Drawing/FillImageBrushTests/CanDrawNegativeOffsetImage_Rgba32.png
new file mode 100644
index 00000000..3a4538c8
--- /dev/null
+++ b/tests/Images/ReferenceOutput/Drawing/FillImageBrushTests/CanDrawNegativeOffsetImage_Rgba32.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2cad09068867e5c56874dd5b44937fd22a386d27ff82e6c5d974444512f1950a
+size 100398