diff --git a/src/ImageProcessor/Filters/Blend.cs b/src/ImageProcessor/Filters/Blend.cs
new file mode 100644
index 000000000..2bc6ace25
--- /dev/null
+++ b/src/ImageProcessor/Filters/Blend.cs
@@ -0,0 +1,77 @@
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessor.Filters
+{
+ using System.Threading.Tasks;
+
+ ///
+ /// Combines two images together by blending the pixels.
+ ///
+ public class Blend : ParallelImageProcessor
+ {
+ ///
+ /// The image to blend.
+ ///
+ private readonly ImageBase toBlend;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The image to blend.
+ /// The opacity of the image to blend. Between 0 and 100.
+ public Blend(ImageBase image, int alpha = 100)
+ {
+ Guard.MustBeBetweenOrEqualTo(alpha, 0, 100, nameof(alpha));
+ this.toBlend = image;
+ this.Value = alpha;
+ }
+
+ ///
+ /// Gets the alpha percentage value.
+ ///
+ public int Value { get; }
+
+ ///
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
+ {
+ int sourceY = sourceRectangle.Y;
+ int sourceBottom = sourceRectangle.Bottom;
+ int startX = sourceRectangle.X;
+ int endX = sourceRectangle.Right;
+ Rectangle bounds = this.toBlend.Bounds;
+ float alpha = this.Value / 100f;
+
+ Parallel.For(
+ startY,
+ endY,
+ y =>
+ {
+ if (y >= sourceY && y < sourceBottom)
+ {
+ for (int x = startX; x < endX; x++)
+ {
+ Color color = source[x, y];
+
+ if (bounds.Contains(x, y))
+ {
+ Color blendedColor = this.toBlend[x, y];
+
+ // Combining colors is dependent on the alpha of the blended color
+ float alphaFactor = alpha > 0 ? alpha : blendedColor.A;
+ float invertedAlphaFactor = 1 - alphaFactor;
+
+ color.R = (color.R * invertedAlphaFactor) + (blendedColor.R * alphaFactor);
+ color.G = (color.G * invertedAlphaFactor) + (blendedColor.G * alphaFactor);
+ color.B = (color.B * invertedAlphaFactor) + (blendedColor.B * alphaFactor);
+ }
+
+ target[x, y] = color;
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/src/ImageProcessor/Filters/ImageFilterExtensions.cs b/src/ImageProcessor/Filters/ImageFilterExtensions.cs
index 73fe8c34c..cc2a7222e 100644
--- a/src/ImageProcessor/Filters/ImageFilterExtensions.cs
+++ b/src/ImageProcessor/Filters/ImageFilterExtensions.cs
@@ -35,6 +35,18 @@ namespace ImageProcessor.Filters
return source.Process(rectangle, new Alpha(percent));
}
+ ///
+ /// Combines the given image together with the current one by blending their pixels.
+ ///
+ /// The image this method extends.
+ /// The image to blend with the currently processing image.
+ /// The opacity of the image image to blend. Must be between 0 and 100.
+ /// The .
+ public static Image Blend(this Image source, ImageBase image, int percent = 100)
+ {
+ return source.Process(source.Bounds, new Blend(image, percent));
+ }
+
///
/// Alters the contrast component of the image.
///
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 4c5c260d8..3560f88b2 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -48,9 +48,10 @@
+
-
+
diff --git a/src/ImageProcessor/Numerics/Rectangle.cs b/src/ImageProcessor/Numerics/Rectangle.cs
index 6fe8a6388..bf3be3498 100644
--- a/src/ImageProcessor/Numerics/Rectangle.cs
+++ b/src/ImageProcessor/Numerics/Rectangle.cs
@@ -140,6 +140,21 @@ namespace ImageProcessor
return !left.Equals(right);
}
+ ///
+ /// Determines if the specfied point is contained within the rectangular region defined by
+ /// this .
+ ///
+ /// The x-coordinate of the given point.
+ /// The y-coordinate of the given point.
+ /// The
+ public bool Contains(int x, int y)
+ {
+ return this.X <= x
+ && x < this.X + this.Width
+ && this.Y <= y
+ && y < this.Y + this.Height;
+ }
+
///
/// Indicates whether this instance and a specified object are equal.
///
diff --git a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
index 479ce6341..96824e264 100644
--- a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
@@ -16,8 +16,9 @@ namespace ImageProcessor.Tests
//{ "Brightness--50", new Brightness(-50) },
//{ "Contrast-50", new Contrast(50) },
//{ "Contrast--50", new Contrast(-50) },
- { "Saturation-50", new Saturation(50) },
- { "Saturation--50", new Saturation(-50) },
+ { "Blend", new Blend(new Image(File.OpenRead("../../TestImages/Formats/Bmp/Car.bmp")),50)},
+ //{ "Saturation-50", new Saturation(50) },
+ //{ "Saturation--50", new Saturation(-50) },
//{ "Alpha--50", new Alpha(50) },
//{ "Invert", new Invert() },
//{ "Sepia", new Sepia() },