diff --git a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs
index 2cb8dc3211..ad93d6f167 100644
--- a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs
@@ -12,168 +12,280 @@ namespace SixLabors.ImageSharp.Processing;
public static class DrawImageExtensions
{
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
float opacity)
{
- var options = source.GetGraphicsOptions();
- return source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- Point.Empty,
- options.ColorBlendingMode,
- options.AlphaCompositionMode,
- opacity));
+ GraphicsOptions options = source.GetGraphicsOptions();
+ return DrawImage(source, image, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The blending mode.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Rectangle rectangle,
+ float opacity)
+ {
+ GraphicsOptions options = source.GetGraphicsOptions();
+ return DrawImage(source, image, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
+ }
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The color blending mode.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
PixelColorBlendingMode colorBlending,
- float opacity) =>
- source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- Point.Empty,
- colorBlending,
- source.GetGraphicsOptions().AlphaCompositionMode,
- opacity));
+ float opacity)
+ => DrawImage(source, image, Point.Empty, colorBlending, opacity);
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The color blending mode.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Rectangle rectangle,
+ PixelColorBlendingMode colorBlending,
+ float opacity)
+ => DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
/// The color blending mode.
/// The alpha composition mode.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
- float opacity) =>
- source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity));
+ float opacity)
+ => DrawImage(source, image, Point.Empty, colorBlending, alphaComposition, opacity);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The color blending mode.
+ /// The alpha composition mode.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Rectangle rectangle,
+ PixelColorBlendingMode colorBlending,
+ PixelAlphaCompositionMode alphaComposition,
+ float opacity)
+ => DrawImage(source, image, Point.Empty, rectangle, colorBlending, alphaComposition, opacity);
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
/// The options, including the blending type and blending amount.
- /// The .
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
- GraphicsOptions options) =>
- source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- Point.Empty,
- options.ColorBlendingMode,
- options.AlphaCompositionMode,
- options.BlendPercentage));
+ GraphicsOptions options)
+ => DrawImage(source, image, Point.Empty, options);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The options, including the blending type and blending amount.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Rectangle rectangle,
+ GraphicsOptions options)
+ => DrawImage(source, image, Point.Empty, rectangle, options);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ float opacity)
+ {
+ GraphicsOptions options = source.GetGraphicsOptions();
+ return DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
+ }
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The location to draw the blended image.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
+ Rectangle rectangle,
float opacity)
{
- var options = source.GetGraphicsOptions();
- return source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- location,
- options.ColorBlendingMode,
- options.AlphaCompositionMode,
- opacity));
+ GraphicsOptions options = source.GetGraphicsOptions();
+ return DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The location to draw the blended image.
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
/// The color blending to apply.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
PixelColorBlendingMode colorBlending,
- float opacity) =>
- source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- location,
- colorBlending,
- source.GetGraphicsOptions().AlphaCompositionMode,
- opacity));
+ float opacity)
+ => DrawImage(source, image, location, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The location to draw the blended image.
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The color blending to apply.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ Rectangle rectangle,
+ PixelColorBlendingMode colorBlending,
+ float opacity)
+ => DrawImage(source, image, location, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The options containing the blend mode and opacity.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ GraphicsOptions options)
+ => DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The options containing the blend mode and opacity.
+ /// The .
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ Rectangle rectangle,
+ GraphicsOptions options)
+ => DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
+
+ ///
+ /// Draws the given image together with the currently processing image by blending their pixels.
+ ///
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
/// The color blending to apply.
/// The alpha composition mode.
- /// The opacity of the image to blend. Must be between 0 and 1.
- /// The .
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
- float opacity) =>
- source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity));
+ float opacity)
+ => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity));
///
- /// Draws the given image together with the current one by blending their pixels.
+ /// Draws the given image together with the currently processing image by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
- /// The location to draw the blended image.
- /// The options containing the blend mode and opacity.
- /// The .
+ /// The current image processing context.
+ /// The image to draw on the currently processing image.
+ /// The location on the currenty processing image at which to draw.
+ /// The rectangle structure that specifies the portion of the image to draw.
+ /// The color blending to apply.
+ /// The alpha composition mode.
+ /// The opacity of the image to draw. Must be between 0 and 1.
+ /// The .
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
- GraphicsOptions options) =>
+ Rectangle rectangle,
+ PixelColorBlendingMode colorBlending,
+ PixelAlphaCompositionMode alphaComposition,
+ float opacity) =>
source.ApplyProcessor(
- new DrawImageProcessor(
- image,
- location,
- options.ColorBlendingMode,
- options.AlphaCompositionMode,
- options.BlendPercentage));
+ new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity),
+ rectangle);
}
diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs
index b7d5b42f8a..9de4f862b8 100644
--- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs
@@ -63,7 +63,7 @@ public class DrawImageProcessor : IImageProcessor
public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
where TPixelBg : unmanaged, IPixel
{
- var visitor = new ProcessorFactoryVisitor(configuration, this, source, sourceRectangle);
+ ProcessorFactoryVisitor visitor = new(configuration, this, source, sourceRectangle);
this.Image.AcceptVisitor(visitor);
return visitor.Result;
}
@@ -88,8 +88,7 @@ public class DrawImageProcessor : IImageProcessor
public void Visit(Image image)
where TPixelFg : unmanaged, IPixel
- {
- this.Result = new DrawImageProcessor(
+ => this.Result = new DrawImageProcessor(
this.configuration,
image,
this.source,
@@ -98,6 +97,5 @@ public class DrawImageProcessor : IImageProcessor
this.definition.ColorBlendingMode,
this.definition.AlphaCompositionMode,
this.definition.Opacity);
- }
}
}
diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
index 82e639f1bd..436a447972 100644
--- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
+++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
@@ -89,7 +89,7 @@ internal class DrawImageProcessor : ImageProcessor
int width = maxX - minX;
- var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
+ Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
// Not a valid operation because rectangle does not overlap with this image.
if (workingRect.Width <= 0 || workingRect.Height <= 0)
@@ -98,7 +98,7 @@ internal class DrawImageProcessor : ImageProcessor
"Cannot draw image because the source image does not overlap the target image.");
}
- var operation = new RowOperation(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
+ DrawImageProcessor.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
ParallelRowIterator.IterateRows(
configuration,
workingRect,
diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
index 0dcb961f84..d017e5ad42 100644
--- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
@@ -119,9 +119,7 @@ public class DrawImageTests
public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y)
{
using Image background = provider.GetImage();
- using Image overlay = new(50, 50);
- Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory overlayMem));
- overlayMem.Span.Fill(Color.Black);
+ using Image overlay = new(50, 50, Color.Black.ToRgba32());
background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F));
@@ -138,6 +136,31 @@ public class DrawImageTests
appendSourceFileOrDescription: false);
}
+ [Theory]
+ [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 10, 10)]
+ [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 25)]
+ [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 50)]
+ [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 50)]
+ public void WorksWithDifferentBounds(TestImageProvider provider, int width, int height)
+ {
+ using Image background = provider.GetImage();
+ using Image overlay = new(50, 50, Color.Black.ToRgba32());
+
+ background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F));
+
+ background.DebugSave(
+ provider,
+ testOutputDetails: $"{width}_{height}",
+ appendPixelTypeToFileName: false,
+ appendSourceFileOrDescription: false);
+
+ background.CompareToReferenceOutput(
+ provider,
+ testOutputDetails: $"{width}_{height}",
+ appendPixelTypeToFileName: false,
+ appendSourceFileOrDescription: false);
+ }
+
[Theory]
[WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)]
public void DrawTransformed(TestImageProvider provider)
@@ -158,12 +181,12 @@ public class DrawImageTests
Point position = new((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2);
image.Mutate(x => x.DrawImage(blend, position, .75F));
- image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false);
+ image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
image.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.002f),
provider,
- appendSourceFileOrDescription: false,
- appendPixelTypeToFileName: false);
+ appendPixelTypeToFileName: false,
+ appendSourceFileOrDescription: false);
}
[Theory]
@@ -179,9 +202,6 @@ public class DrawImageTests
Assert.Contains("does not overlap", ex.ToString());
- void Test()
- {
- background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions()));
- }
+ void Test() => background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions()));
}
}
diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png
new file mode 100644
index 0000000000..64ce14d509
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f353ee06664a6ff27c533af63cffb9eac4917103ba0b7fff9084fb4d2d42fed7
+size 155
diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png
new file mode 100644
index 0000000000..7e0466186a
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:af198da8f611eb97f3e4e358cb097cd292771d52e991de76495f073c1f1b9338
+size 154
diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png
new file mode 100644
index 0000000000..6b93e597eb
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:35bda87f28e03c5ed0d45412e367fae9b04b7684f5242dc20e7709e8ed71cd86
+size 156
diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png
new file mode 100644
index 0000000000..540082dfdf
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f8b9ff745592bb0e0a365cb0985a5519bf567fc73a09211c88bcda51356f9202
+size 155