diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs
index 58459ebc5d..981cf1bef4 100644
--- a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs
@@ -15,98 +15,126 @@ namespace SixLabors.ImageSharp.Processing
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// 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 .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ float opacity) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ Point.Empty,
+ GraphicsOptions.Default.ColorBlendingMode,
+ GraphicsOptions.Default.AlphaCompositionMode,
+ opacity));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// 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 .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ PixelColorBlendingMode colorBlending,
+ float opacity) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ Point.Empty,
+ colorBlending,
+ GraphicsOptions.Default.AlphaCompositionMode,
+ opacity));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// The image this method extends.
/// The image to blend with 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 .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity));
+ 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));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The options, including the blending type and blending amount.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ GraphicsOptions options) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ Point.Empty,
+ options.ColorBlendingMode,
+ options.AlphaCompositionMode,
+ options.BlendPercentage));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// 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 .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ float opacity) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ location,
+ GraphicsOptions.Default.ColorBlendingMode,
+ GraphicsOptions.Default.AlphaCompositionMode,
+ opacity));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The location to draw the blended image.
/// The color blending to apply.
/// The opacity of the image to blend. Must be between 0 and 1.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ PixelColorBlendingMode colorBlending,
+ float opacity) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ location,
+ colorBlending,
+ GraphicsOptions.Default.AlphaCompositionMode,
+ opacity));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The location to draw the blended image.
@@ -114,24 +142,34 @@ namespace SixLabors.ImageSharp.Processing
/// The alpha composition mode.
/// The opacity of the image to blend. Must be between 0 and 1.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity));
+ 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));
///
/// Draws the given image together with the current one by blending their pixels.
///
- /// The pixel format of the destination image.
- /// The pixel format of the source image.
/// 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 .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options)
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
- => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage));
+ public static IImageProcessingContext DrawImage(
+ this IImageProcessingContext source,
+ Image image,
+ Point location,
+ GraphicsOptions options) =>
+ source.ApplyProcessor(
+ new DrawImageProcessor(
+ image,
+ location,
+ options.ColorBlendingMode,
+ options.AlphaCompositionMode,
+ options.BlendPercentage));
}
}
\ No newline at end of file
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
index 6c03537eb3..0fbef9afea 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
@@ -13,14 +13,90 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
+ public class DrawImageProcessor : IImageProcessor
+ {
+ public DrawImageProcessor(
+ Image image,
+ Point location,
+ PixelColorBlendingMode colorBlendingMode,
+ PixelAlphaCompositionMode alphaCompositionMode,
+ float opacity)
+ {
+ this.Image = image;
+ this.Location = location;
+ this.ColorBlendingMode = colorBlendingMode;
+ this.AlphaCompositionMode = alphaCompositionMode;
+ this.Opacity = opacity;
+ }
+
+ ///
+ /// Gets the image to blend
+ ///
+ public Image Image { get; }
+
+ ///
+ /// Gets the location to draw the blended image
+ ///
+ public Point Location { get; }
+
+ ///
+ /// Gets the blending mode to use when drawing the image.
+ ///
+ public PixelColorBlendingMode ColorBlendingMode { get; }
+
+ ///
+ /// Gets the Alpha blending mode to use when drawing the image.
+ ///
+ public PixelAlphaCompositionMode AlphaCompositionMode { get; }
+
+ ///
+ /// Gets the opacity of the image to blend
+ ///
+ public float Opacity { get; }
+
+ ///
+ public IImageProcessor CreatePixelSpecificProcessor()
+ where TPixelBg : struct, IPixel
+ {
+ var visitor = new ProcessorFactoryVisitor(this);
+ this.Image.AcceptVisitor(visitor);
+ return visitor.Result;
+ }
+
+ private class ProcessorFactoryVisitor : IImageVisitor
+ where TPixelBg : struct, IPixel
+ {
+ private readonly DrawImageProcessor definition;
+
+ public ProcessorFactoryVisitor(DrawImageProcessor definition)
+ {
+ this.definition = definition;
+ }
+
+ public IImageProcessor Result { get; private set; }
+
+ public void Visit(Image image)
+ where TPixelFg : struct, IPixel
+ {
+ this.Result = new DrawImageProcessor(
+ image,
+ this.definition.Location,
+ this.definition.ColorBlendingMode,
+ this.definition.AlphaCompositionMode,
+ this.definition.Opacity
+ );
+ }
+ }
+ }
+
///
/// Combines two images together by blending the pixels.
///
- /// The pixel format of destination image.
- /// The pixel format of source image.
- internal class DrawImageProcessor : ImageProcessor
- where TPixelDst : struct, IPixel
- where TPixelSrc : struct, IPixel
+ /// The pixel format of destination image.
+ /// The pixel format of source image.
+ internal class DrawImageProcessor : ImageProcessor
+ where TPixelBg : struct, IPixel
+ where TPixelFg : struct, IPixel
{
///
/// Initializes a new instance of the class.
@@ -30,20 +106,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
/// The blending mode to use when drawing the image.
/// The Alpha blending mode to use when drawing the image.
/// The opacity of the image to blend. Must be between 0 and 1.
- public DrawImageProcessor(Image image, Point location, PixelColorBlendingMode colorBlendingMode, PixelAlphaCompositionMode alphaCompositionMode, float opacity)
+ public DrawImageProcessor(
+ Image image,
+ Point location,
+ PixelColorBlendingMode colorBlendingMode,
+ PixelAlphaCompositionMode alphaCompositionMode,
+ float opacity)
{
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity));
this.Image = image;
this.Opacity = opacity;
- this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode);
+ this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode);
this.Location = location;
}
///
/// Gets the image to blend
///
- public Image Image { get; }
+ public Image Image { get; }
///
/// Gets the opacity of the image to blend
@@ -53,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
///
/// Gets the pixel blender
///
- public PixelBlender Blender { get; }
+ public PixelBlender Blender { get; }
///
/// Gets the location to draw the blended image
@@ -61,10 +142,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
public Point Location { get; }
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(
+ ImageFrame source,
+ Rectangle sourceRectangle,
+ Configuration configuration)
{
- Image targetImage = this.Image;
- PixelBlender blender = this.Blender;
+ Image targetImage = this.Image;
+ PixelBlender blender = this.Blender;
int locationY = this.Location.Y;
// Align start/end positions.
@@ -84,7 +168,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
// not a valid operation because rectangle does not overlap with this image.
if (workingRect.Width <= 0 || workingRect.Height <= 0)
{
- throw new ImageProcessingException("Cannot draw image because the source image does not overlap the target image.");
+ throw new ImageProcessingException(
+ "Cannot draw image because the source image does not overlap the target image.");
}
ParallelHelper.IterateRows(
@@ -94,10 +179,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
for (int y = rows.Min; y < rows.Max; y++)
{
- Span background = source.GetPixelRowSpan(y).Slice(minX, width);
- Span foreground =
+ Span background = source.GetPixelRowSpan(y).Slice(minX, width);
+ Span foreground =
targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width);
- blender.Blend(configuration, background, background, foreground, this.Opacity);
+ blender.Blend(configuration, background, background, foreground, this.Opacity);
}
});
}