diff --git a/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs b/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs index 73a3f7b269..9eea86a443 100644 --- a/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs +++ b/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs @@ -1,5 +1,6 @@ namespace Avalonia.Media.Imaging { + // TODO12 split the enum into two: composite mode and blend mode. (And rename Blending to Blend at the same time). /// /// Controls the way the bitmaps are drawn together. /// @@ -54,6 +55,66 @@ namespace Avalonia.Media.Imaging /// /// Display the sum of the source image and destination image. /// - Plus + Plus, + /// + /// Multiplies the complements of the backdrop and source color values, then complements the result. + /// + Screen, + /// + /// Multiplies or screens the colors, depending on the backdrop color value. + /// + Overlay, + /// + /// Selects the darker of the backdrop and source colors. + /// + Darken, + /// + /// Selects the lighter of the backdrop and source colors. + /// + Lighten, + /// + /// Darkens the backdrop color to reflect the source color. + /// + ColorDodge, + /// + /// Multiplies or screens the colors, depending on the source color value. + /// + ColorBurn, + /// + /// Darkens or lightens the colors, depending on the source color value. + /// + HardLight, + /// + /// Subtracts the darker of the two constituent colors from the lighter color. + /// + SoftLight, + /// + /// Produces an effect similar to that of the Difference mode but lower in contrast. + /// + Difference, + /// + /// The source color is multiplied by the destination color and replaces the destination + /// + Exclusion, + /// + /// Creates a color with the hue of the source color and the saturation and luminosity of the backdrop color. + /// + Multiply, + /// + /// Creates a color with the hue of the source color and the saturation and luminosity of the backdrop color. + /// + Hue, + /// + /// Creates a color with the saturation of the source color and the hue and luminosity of the backdrop color. + /// + Saturation, + /// + /// Creates a color with the hue and saturation of the source color and the luminosity of the backdrop color. + /// + Color, + /// + /// Creates a color with the luminosity of the source color and the hue and saturation of the backdrop color. + /// + Luminosity } } diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs index 1b5fe123da..5e8ee86c72 100644 --- a/src/Avalonia.Controls/Image.cs +++ b/src/Avalonia.Controls/Image.cs @@ -17,6 +17,12 @@ namespace Avalonia.Controls /// public static readonly StyledProperty SourceProperty = AvaloniaProperty.Register(nameof(Source)); + + /// + /// Defines the property. + /// + public static readonly StyledProperty BlendModeProperty = + AvaloniaProperty.Register(nameof(BlendMode)); /// /// Defines the property. @@ -34,7 +40,7 @@ namespace Avalonia.Controls static Image() { - AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty); + AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty, BlendModeProperty); AffectsMeasure(SourceProperty, StretchProperty, StretchDirectionProperty); AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue(AutomationControlType.Image); } @@ -49,6 +55,15 @@ namespace Avalonia.Controls set => SetValue(SourceProperty, value); } + /// + /// Gets or sets the blend mode for the image. + /// + public BitmapBlendingMode BlendMode + { + get => GetValue(BlendModeProperty); + set => SetValue(BlendModeProperty, value); + } + /// /// Gets or sets a value controlling how the image will be stretched. /// @@ -91,7 +106,10 @@ namespace Avalonia.Controls Rect sourceRect = new Rect(sourceSize) .CenterRect(new Rect(destRect.Size / scale)); - context.DrawImage(source, sourceRect, destRect); + using (context.PushRenderOptions(RenderOptions with { BitmapBlendingMode = BlendMode })) + { + context.DrawImage(source, sourceRect, destRect); + } } } diff --git a/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs b/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs index ba7ab60fb0..add72caa30 100644 --- a/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs +++ b/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs @@ -29,36 +29,38 @@ namespace Avalonia.Skia public static SKBlendMode ToSKBlendMode(this BitmapBlendingMode blendingMode) { - switch (blendingMode) + return blendingMode switch { - case BitmapBlendingMode.Unspecified: - case BitmapBlendingMode.SourceOver: - return SKBlendMode.SrcOver; - case BitmapBlendingMode.Source: - return SKBlendMode.Src; - case BitmapBlendingMode.SourceIn: - return SKBlendMode.SrcIn; - case BitmapBlendingMode.SourceOut: - return SKBlendMode.SrcOut; - case BitmapBlendingMode.SourceAtop: - return SKBlendMode.SrcATop; - case BitmapBlendingMode.Destination: - return SKBlendMode.Dst; - case BitmapBlendingMode.DestinationIn: - return SKBlendMode.DstIn; - case BitmapBlendingMode.DestinationOut: - return SKBlendMode.DstOut; - case BitmapBlendingMode.DestinationOver: - return SKBlendMode.DstOver; - case BitmapBlendingMode.DestinationAtop: - return SKBlendMode.DstATop; - case BitmapBlendingMode.Xor: - return SKBlendMode.Xor; - case BitmapBlendingMode.Plus: - return SKBlendMode.Plus; - default: - throw new ArgumentOutOfRangeException(nameof(blendingMode), blendingMode, null); - } + BitmapBlendingMode.Unspecified => SKBlendMode.SrcOver, + BitmapBlendingMode.SourceOver => SKBlendMode.SrcOver, + BitmapBlendingMode.Source => SKBlendMode.Src, + BitmapBlendingMode.SourceIn => SKBlendMode.SrcIn, + BitmapBlendingMode.SourceOut => SKBlendMode.SrcOut, + BitmapBlendingMode.SourceAtop => SKBlendMode.SrcATop, + BitmapBlendingMode.Destination => SKBlendMode.Dst, + BitmapBlendingMode.DestinationIn => SKBlendMode.DstIn, + BitmapBlendingMode.DestinationOut => SKBlendMode.DstOut, + BitmapBlendingMode.DestinationOver => SKBlendMode.DstOver, + BitmapBlendingMode.DestinationAtop => SKBlendMode.DstATop, + BitmapBlendingMode.Xor => SKBlendMode.Xor, + BitmapBlendingMode.Plus => SKBlendMode.Plus, + BitmapBlendingMode.Screen => SKBlendMode.Screen, + BitmapBlendingMode.Overlay => SKBlendMode.Overlay, + BitmapBlendingMode.Darken => SKBlendMode.Darken, + BitmapBlendingMode.Lighten => SKBlendMode.Lighten, + BitmapBlendingMode.ColorDodge => SKBlendMode.ColorDodge, + BitmapBlendingMode.ColorBurn => SKBlendMode.ColorBurn, + BitmapBlendingMode.HardLight => SKBlendMode.HardLight, + BitmapBlendingMode.SoftLight => SKBlendMode.SoftLight, + BitmapBlendingMode.Difference => SKBlendMode.Difference, + BitmapBlendingMode.Exclusion => SKBlendMode.Exclusion, + BitmapBlendingMode.Multiply => SKBlendMode.Multiply, + BitmapBlendingMode.Hue => SKBlendMode.Hue, + BitmapBlendingMode.Saturation => SKBlendMode.Saturation, + BitmapBlendingMode.Color => SKBlendMode.Color, + BitmapBlendingMode.Luminosity => SKBlendMode.Luminosity, + _ => throw new ArgumentOutOfRangeException(nameof(blendingMode), blendingMode, null) + }; } public static SKPoint ToSKPoint(this Point p) diff --git a/tests/Avalonia.RenderTests/Controls/ImageBlendTests.cs b/tests/Avalonia.RenderTests/Controls/ImageBlendTests.cs new file mode 100644 index 0000000000..1f8f5d2241 --- /dev/null +++ b/tests/Avalonia.RenderTests/Controls/ImageBlendTests.cs @@ -0,0 +1,83 @@ +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using Xunit; + +#if AVALONIA_SKIA +namespace Avalonia.Skia.RenderTests +#else +namespace Avalonia.Direct2D1.RenderTests.Controls +#endif +{ + public class ImageBlendTests : TestBase + { + private readonly Bitmap _bitmapBase; + private readonly Bitmap _bitmapOver; + + public ImageBlendTests() + : base(@"Controls\Image\blend") + { + _bitmapBase = new Bitmap(Path.Combine(OutputPath, "Cat.jpg")); + _bitmapOver = new Bitmap(Path.Combine(OutputPath, "ColourShading - by Stib.png")); + } + + [Fact] + public async Task Image_Blend_Nothing() => await TestBlendMode(BitmapBlendingMode.Unspecified); + [Fact] + public async Task Image_Blend_Plus() => await TestBlendMode(BitmapBlendingMode.Plus); + [Fact] + public async Task Image_Blend_Screen() => await TestBlendMode(BitmapBlendingMode.Screen); + [Fact] + public async Task Image_Blend_Overlay() => await TestBlendMode(BitmapBlendingMode.Overlay); + [Fact] + public async Task Image_Blend_Darken() => await TestBlendMode(BitmapBlendingMode.Darken); + [Fact] + public async Task Image_Blend_Lighten() => await TestBlendMode(BitmapBlendingMode.Lighten); + [Fact] + public async Task Image_Blend_ColorDodge() => await TestBlendMode(BitmapBlendingMode.ColorDodge); + [Fact] + public async Task Image_Blend_ColorBurn() => await TestBlendMode(BitmapBlendingMode.ColorBurn); + [Fact] + public async Task Image_Blend_HardLight() => await TestBlendMode(BitmapBlendingMode.HardLight); + [Fact] + public async Task Image_Blend_SoftLight() => await TestBlendMode(BitmapBlendingMode.SoftLight); + [Fact] + public async Task Image_Blend_Difference() => await TestBlendMode(BitmapBlendingMode.Difference); + [Fact] + public async Task Image_Blend_Exclusion() => await TestBlendMode(BitmapBlendingMode.Exclusion); + [Fact] + public async Task Image_Blend_Multiply() => await TestBlendMode(BitmapBlendingMode.Multiply); + [Fact] + public async Task Image_Blend_Hue() => await TestBlendMode(BitmapBlendingMode.Hue); + [Fact] + public async Task Image_Blend_Saturation() => await TestBlendMode(BitmapBlendingMode.Saturation); + [Fact] + public async Task Image_Blend_Color() => await TestBlendMode(BitmapBlendingMode.Color); + [Fact] + public async Task Image_Blend_Luminosity() => await TestBlendMode(BitmapBlendingMode.Luminosity); + + private async Task TestBlendMode(BitmapBlendingMode blendMode, [CallerMemberName] string testName = "") + { + var panel = new Panel(); + panel.Children.Add(new Image() { Source = _bitmapBase }); + panel.Children.Add(new Image() { Source = _bitmapOver, BlendMode = blendMode }); + + var target = new Decorator + { + Width = 512, + Height = 512, + Child = new Border + { + Background = Brushes.Red, + Child = panel + } + }; + + await RenderToFile(target,testName); + CompareImages(testName); + } + } +} diff --git a/tests/Avalonia.RenderTests/Controls/ImageCompositionTests.cs b/tests/Avalonia.RenderTests/Controls/ImageCompositionTests.cs new file mode 100644 index 0000000000..8236468aeb --- /dev/null +++ b/tests/Avalonia.RenderTests/Controls/ImageCompositionTests.cs @@ -0,0 +1,70 @@ +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using Xunit; + +#if AVALONIA_SKIA +namespace Avalonia.Skia.RenderTests +#else +namespace Avalonia.Direct2D1.RenderTests.Controls +#endif +{ + public class ImageCompositionTests : TestBase + { + private readonly Bitmap _bitmapA; + private readonly Bitmap _bitmapB; + + public ImageCompositionTests() + : base(@"Controls\Image\composition") + { + _bitmapA = new Bitmap(Path.Combine(OutputPath, "A.png")); + _bitmapB = new Bitmap(Path.Combine(OutputPath, "B.png")); + } + [Fact] + public async Task Image_Blend_SourceOver() => await TestCompositeMode(BitmapBlendingMode.SourceOver); + [Fact] + public async Task Image_Blend_Source() => await TestCompositeMode(BitmapBlendingMode.Source); + [Fact] + public async Task Image_Blend_SourceIn() => await TestCompositeMode(BitmapBlendingMode.SourceIn); + [Fact] + public async Task Image_Blend_SourceOut() => await TestCompositeMode(BitmapBlendingMode.SourceOut); + [Fact] + public async Task Image_Blend_SourceAtop() => await TestCompositeMode(BitmapBlendingMode.SourceAtop); + [Fact] + public async Task Image_Blend_Destination() => await TestCompositeMode(BitmapBlendingMode.Destination); + [Fact] + public async Task Image_Blend_DestinationIn() => await TestCompositeMode(BitmapBlendingMode.DestinationIn); + [Fact] + public async Task Image_Blend_DestinationOut() => await TestCompositeMode(BitmapBlendingMode.DestinationOut); + [Fact] + public async Task Image_Blend_DestinationOver() => await TestCompositeMode(BitmapBlendingMode.DestinationOver); + [Fact] + public async Task Image_Blend_DestinationAtop() => await TestCompositeMode(BitmapBlendingMode.DestinationAtop); + [Fact] + public async Task Image_Blend_Xor() => await TestCompositeMode(BitmapBlendingMode.Xor); + + private async Task TestCompositeMode(BitmapBlendingMode blendMode, [CallerMemberName] string testName = "") + { + var panel = new Panel(); + panel.Children.Add(new Image() { Source = _bitmapA }); + panel.Children.Add(new Image() { Source = _bitmapB, BlendMode = blendMode }); + + var target = new Decorator + { + Width = 512, + Height = 512, + Child = new Border + { + Background = Brushes.Transparent, + Child = panel + } + }; + + await RenderToFile(target,testName); + CompareImages(testName); + } + } +} diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Cat.jpg b/tests/TestFiles/Direct2D1/Controls/Image/blend/Cat.jpg new file mode 100644 index 0000000000..01de4614f6 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Cat.jpg differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/ColourShading - by Stib.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/ColourShading - by Stib.png new file mode 100644 index 0000000000..ef464dedb4 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/ColourShading - by Stib.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Color.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Color.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Color.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorBurn.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorBurn.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorBurn.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorDodge.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorDodge.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_ColorDodge.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Darken.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Darken.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Darken.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Difference.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Difference.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Difference.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Exclusion.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Exclusion.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Exclusion.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_HardLight.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_HardLight.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_HardLight.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Hue.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Hue.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Hue.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Lighten.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Lighten.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Lighten.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Luminosity.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Luminosity.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Luminosity.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Multiply.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Multiply.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Multiply.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Nothing.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Nothing.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Nothing.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Overlay.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Overlay.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Overlay.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Plus.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Plus.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Plus.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Saturation.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Saturation.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Saturation.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Screen.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Screen.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_Screen.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_SoftLight.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_SoftLight.expected.png new file mode 100644 index 0000000000..c6f12e8b43 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/blend/Image_Blend_SoftLight.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/A.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/A.png new file mode 100644 index 0000000000..fb3dacda4c Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/A.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/B.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/B.png new file mode 100644 index 0000000000..13aaf23dde Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/B.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Destination.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Destination.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Destination.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationIn.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationIn.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationIn.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOut.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOut.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOut.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOver.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOver.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_DestinationOver.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Source.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Source.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Source.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceAtop.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceAtop.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceAtop.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceIn.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceIn.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceIn.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOut.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOut.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOut.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOver.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOver.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_SourceOver.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Xor.expected.png b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Xor.expected.png new file mode 100644 index 0000000000..030552a395 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Image/composition/Image_Blend_Xor.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Cat.jpg b/tests/TestFiles/Skia/Controls/Image/blend/Cat.jpg new file mode 100644 index 0000000000..01de4614f6 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Cat.jpg differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/ColourShading - by Stib.png b/tests/TestFiles/Skia/Controls/Image/blend/ColourShading - by Stib.png new file mode 100644 index 0000000000..ef464dedb4 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/ColourShading - by Stib.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Color.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Color.expected.png new file mode 100644 index 0000000000..b6e6b7c212 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Color.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorBurn.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorBurn.expected.png new file mode 100644 index 0000000000..1812a59efd Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorBurn.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorDodge.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorDodge.expected.png new file mode 100644 index 0000000000..ff12a5d501 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_ColorDodge.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Darken.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Darken.expected.png new file mode 100644 index 0000000000..c6edbe00c9 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Darken.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Difference.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Difference.expected.png new file mode 100644 index 0000000000..e9456b699e Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Difference.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Exclusion.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Exclusion.expected.png new file mode 100644 index 0000000000..ced05f85e2 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Exclusion.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_HardLight.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_HardLight.expected.png new file mode 100644 index 0000000000..d6d56f99ec Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_HardLight.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Hue.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Hue.expected.png new file mode 100644 index 0000000000..832793eb1a Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Hue.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Lighten.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Lighten.expected.png new file mode 100644 index 0000000000..9f0ae673ff Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Lighten.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Luminosity.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Luminosity.expected.png new file mode 100644 index 0000000000..f772c5ce34 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Luminosity.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Multiply.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Multiply.expected.png new file mode 100644 index 0000000000..5fc0c93605 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Multiply.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Nothing.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Nothing.expected.png new file mode 100644 index 0000000000..4a5f0ea2aa Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Nothing.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Overlay.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Overlay.expected.png new file mode 100644 index 0000000000..843ce50f75 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Overlay.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Plus.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Plus.expected.png new file mode 100644 index 0000000000..ae159039bb Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Plus.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Saturation.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Saturation.expected.png new file mode 100644 index 0000000000..9744e24f81 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Saturation.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Screen.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Screen.expected.png new file mode 100644 index 0000000000..fe448fc3dc Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_Screen.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_SoftLight.expected.png b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_SoftLight.expected.png new file mode 100644 index 0000000000..d39c01f973 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/blend/Image_Blend_SoftLight.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/A.png b/tests/TestFiles/Skia/Controls/Image/composition/A.png new file mode 100644 index 0000000000..fb3dacda4c Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/A.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/B.png b/tests/TestFiles/Skia/Controls/Image/composition/B.png new file mode 100644 index 0000000000..13aaf23dde Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/B.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Destination.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Destination.expected.png new file mode 100644 index 0000000000..bcb03de2e2 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Destination.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png new file mode 100644 index 0000000000..1f0cea9360 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationAtop.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationIn.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationIn.expected.png new file mode 100644 index 0000000000..ebd1b2978d Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationIn.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOut.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOut.expected.png new file mode 100644 index 0000000000..ebf07dc002 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOut.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOver.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOver.expected.png new file mode 100644 index 0000000000..adda03eb8b Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_DestinationOver.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Source.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Source.expected.png new file mode 100644 index 0000000000..cbb1398065 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Source.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceAtop.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceAtop.expected.png new file mode 100644 index 0000000000..33bdf8efc4 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceAtop.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceIn.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceIn.expected.png new file mode 100644 index 0000000000..f1989a2a77 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceIn.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOut.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOut.expected.png new file mode 100644 index 0000000000..a2975afd06 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOut.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOver.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOver.expected.png new file mode 100644 index 0000000000..1438009f98 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_SourceOver.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Xor.expected.png b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Xor.expected.png new file mode 100644 index 0000000000..ee74b79f52 Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Image/composition/Image_Blend_Xor.expected.png differ