diff --git a/.gitignore b/.gitignore index fb8af2320..8034c8c89 100644 --- a/.gitignore +++ b/.gitignore @@ -217,3 +217,4 @@ artifacts/ #CodeCoverage **/CodeCoverage/* docs/ +/samples/AvatarWithRoundedCorner/output diff --git a/ImageSharp.sln b/ImageSharp.sln index 2e0cbd52e..35998e1aa 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.7 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" ProjectSection(SolutionItems) = preProject @@ -45,6 +45,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Benchmarks", "te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Sandbox46", "tests\ImageSharp.Sandbox46\ImageSharp.Sandbox46.csproj", "{96188137-5FA6-4924-AB6E-4EFF79C6E0BB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7CC6D57E-B916-43B8-B315-A0BB92F260A2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarWithRoundedCorner", "samples\AvatarWithRoundedCorner\AvatarWithRoundedCorner.csproj", "{844FC582-4E78-4371-847D-EFD4D1103578}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -127,6 +131,18 @@ Global {96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Release|x64.Build.0 = Release|Any CPU {96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Release|x86.ActiveCfg = Release|Any CPU {96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Release|x86.Build.0 = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.Build.0 = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.ActiveCfg = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.Build.0 = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.ActiveCfg = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.Build.0 = Debug|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.ActiveCfg = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.Build.0 = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.ActiveCfg = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.Build.0 = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.ActiveCfg = Release|Any CPU + {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -139,5 +155,6 @@ Global {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {2BF743D8-2A06-412D-96D7-F448F00C5EA5} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {96188137-5FA6-4924-AB6E-4EFF79C6E0BB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} + {844FC582-4E78-4371-847D-EFD4D1103578} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2} EndGlobalSection EndGlobal diff --git a/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj b/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj new file mode 100644 index 000000000..e000aacf1 --- /dev/null +++ b/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp1.1 + + + + + + + \ No newline at end of file diff --git a/samples/AvatarWithRoundedCorner/Program.cs b/samples/AvatarWithRoundedCorner/Program.cs new file mode 100644 index 000000000..56b30744c --- /dev/null +++ b/samples/AvatarWithRoundedCorner/Program.cs @@ -0,0 +1,63 @@ + + +namespace AvatarWithRoundedCorner +{ + using System; + using System.Numerics; + using ImageSharp; + using SixLabors.Shapes; + + class Program + { + static void Main(string[] args) + { + + using (var image = Image.Load("fb.jpg")) + { + image.Resize(new ImageSharp.Processing.ResizeOptions + { + Size = new ImageSharp.Size(200, 200), + Mode = ImageSharp.Processing.ResizeMode.Crop + }); + + ApplyRoundedCourners(image, 30); + System.IO.Directory.CreateDirectory("output"); + image.Save("output/fb.png"); + } + } + + public static void ApplyRoundedCourners(Image img, float cornerRadius) + { + var corners = BuildCorners(img.Width, img.Height, cornerRadius); + // now we have our corners time to draw them + img.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true) + { + BlenderMode = ImageSharp.PixelFormats.PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background + }); + } + + public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius) + { + // first create a square + var rect = new SixLabors.Shapes.Rectangle(-0.5f, -0.5f, cornerRadius, cornerRadius); + + // then cut out of the square a circle so we are left with a corner + var cornerToptLeft = rect.Clip(new SixLabors.Shapes.Ellipse(cornerRadius-0.5f, cornerRadius - 0.5f, cornerRadius)); + + // corner is now a corner shape positions top left + //lets make 3 more positioned correctly, we cando that by translating the orgional artound the center of the image + var center = new Vector2(imageWidth / 2, imageHeight / 2); + var angle = Math.PI / 2f; + + float rightPos = imageWidth - cornerToptLeft.Bounds.Width +1; + float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1; + + // move it across the widthof the image - the width of the shape + var cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0); + var cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos); + var cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos); + + return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight); + } + } +} \ No newline at end of file diff --git a/samples/AvatarWithRoundedCorner/fb.jpg b/samples/AvatarWithRoundedCorner/fb.jpg new file mode 100644 index 000000000..7241890e2 --- /dev/null +++ b/samples/AvatarWithRoundedCorner/fb.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93bb4d6281dc1e845db57e836e0dca30b7a4062e81044efb27ad4d8b1a33130c +size 15787 diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index a0e4495b6..a2cbb0719 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -16,79 +16,79 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Src(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, source); + source.W *= opacity; + return Compose(Vector4.Zero, source, source).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Atop(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, source); + return Compose(backdrop, Vector4.Zero, source).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Over(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, source); + source.W *= opacity; + return Compose(backdrop, source, source).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 In(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, source); + return Compose(Vector4.Zero, Vector4.Zero, source).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Out(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, Vector4.Zero); + source.W *= opacity; + return Compose(Vector4.Zero, source, Vector4.Zero).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Dest(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, backdrop); + return Compose(backdrop, Vector4.Zero, backdrop).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, backdrop); + source.W *= opacity; + return Compose(Vector4.Zero, source, backdrop).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, backdrop); + source.W *= opacity; + return Compose(backdrop, source, backdrop).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, backdrop); + return Compose(Vector4.Zero, Vector4.Zero, backdrop).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, Vector4.Zero); + return Compose(backdrop, Vector4.Zero, Vector4.Zero).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Clear(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, Vector4.Zero); + return Compose(Vector4.Zero, Vector4.Zero, Vector4.Zero).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Xor(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Zero); + source.W *= opacity; + return Compose(backdrop, source, Vector4.Zero).Blend(backdrop, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index 68bd65041..1b60481b6 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -48,15 +48,12 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float opacity) { -<# - if(sourceVar != "Vector4.Zero") - { -#> - <#=sourceVar#>.W *= opacity; -<# - } -#> - return Compose(<#=destVar#>, <#=sourceVar#>, <#=blendVar#>); + <# if(sourceVar != "Vector4.Zero") { + #> + <#=sourceVar#>.W *= opacity; + <# + } #> + return Compose(<#=destVar#>, <#=sourceVar#>, <#=blendVar#>).Blend(backdrop, opacity); } <# diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs index bbb6ca4de..bc7bb2d90 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs @@ -31,8 +31,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Normal(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, source); + return Over(backdrop, source, opacity); } /// @@ -45,8 +44,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, backdrop * source); + return Compose(backdrop, source, backdrop * source).Blend(backdrop, opacity); } /// @@ -59,8 +57,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Add(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Min(Vector4.One, backdrop + source)); + return Compose(backdrop, source, Vector4.Min(Vector4.One, backdrop + source)).Blend(backdrop, opacity); } /// @@ -73,8 +70,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Substract(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Max(Vector4.Zero, backdrop - source)); + return Compose(backdrop, source, Vector4.Max(Vector4.Zero, backdrop - source)).Blend(backdrop, opacity); } /// @@ -87,8 +83,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Screen(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source))); + return Compose(backdrop, source, Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source))).Blend(backdrop, opacity); } /// @@ -101,8 +96,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Darken(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Min(backdrop, source)); + return Compose(backdrop, source, Vector4.Min(backdrop, source)).Blend(backdrop, opacity); } /// @@ -115,8 +109,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Lighten(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Max(backdrop, source)); + return Compose(backdrop, source, Vector4.Max(backdrop, source)).Blend(backdrop, opacity); } /// @@ -134,7 +127,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders float cg = OverlayValueFunction(backdrop.Y, source.Y); float cb = OverlayValueFunction(backdrop.Z, source.Z); - return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); + return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))).Blend(backdrop, opacity); } /// @@ -147,12 +140,11 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLight(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; float cr = OverlayValueFunction(source.X, backdrop.X); float cg = OverlayValueFunction(source.Y, backdrop.Y); float cb = OverlayValueFunction(source.Z, backdrop.Z); - return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); + return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))).Blend(backdrop, opacity); } /// @@ -186,10 +178,16 @@ namespace ImageSharp.PixelFormats.PixelBlenders float a = xw + bw + sw; // calculate final value - xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / a; + xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); xform.W = a; return xform; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector4 Blend(this Vector4 source, Vector4 backdrop, float opacity) + { + return Vector4.Lerp(backdrop, source, opacity); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs b/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs index a3df1803d..de10fd24f 100644 --- a/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs +++ b/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs @@ -18,14 +18,16 @@ namespace ImageSharp.Tests.Drawing .Select(x=> new object[] { x }); [Theory] - [WithBlankImages(nameof(modes), 100, 100, PixelTypes.Rgba32)] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] public void DrawBlendedValues(TestImageProvider provider, PixelBlenderMode mode) where TPixel : struct, IPixel { using (var img = provider.GetImage()) { - img.Fill(NamedColors.DarkBlue, new Rectangle(0, 40, 100, 20)); - img.Fill(NamedColors.HotPink, new Rectangle(40, 0, 20, 100), new ImageSharp.GraphicsOptions(true) + var scaleX = (img.Width / 100); + var scaleY = (img.Height / 100); + img.Fill(NamedColors.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY)); + img.Fill(NamedColors.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY), new ImageSharp.GraphicsOptions(true) { BlenderMode = mode }); @@ -34,18 +36,20 @@ namespace ImageSharp.Tests.Drawing } [Theory] - [WithBlankImages(nameof(modes), 100, 100, PixelTypes.Rgba32)] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] public void DrawBlendedValues_transparent(TestImageProvider provider, PixelBlenderMode mode) where TPixel : struct, IPixel { using (var img = provider.GetImage()) { - img.Fill(NamedColors.DarkBlue, new Rectangle(0, 40, 100, 20)); - img.Fill(NamedColors.HotPink, new Rectangle(20, 0, 30, 100), new ImageSharp.GraphicsOptions(true) + var scaleX = (img.Width / 100); + var scaleY = (img.Height / 100); + img.Fill(NamedColors.DarkBlue, new Rectangle(0* scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY)); + img.Fill(NamedColors.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY), new ImageSharp.GraphicsOptions(true) { BlenderMode = mode }); - img.Fill(NamedColors.Transparent, new Rectangle(40, 0, 20, 100), new ImageSharp.GraphicsOptions(true) + img.Fill(NamedColors.Transparent, new SixLabors.Shapes.Ellipse(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY), new ImageSharp.GraphicsOptions(true) { BlenderMode = mode }); @@ -53,16 +57,17 @@ namespace ImageSharp.Tests.Drawing } } - [Theory] - [WithBlankImages(nameof(modes), 100, 100, PixelTypes.Rgba32)] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] public void DrawBlendedValues_transparent50Percent(TestImageProvider provider, PixelBlenderMode mode) where TPixel : struct, IPixel { using (var img = provider.GetImage()) { - img.Fill(NamedColors.DarkBlue, new Rectangle(0, 40, 100, 20)); - img.Fill(NamedColors.HotPink, new Rectangle(20, 0, 30, 100), new ImageSharp.GraphicsOptions(true) + var scaleX = (img.Width / 100); + var scaleY = (img.Height / 100); + img.Fill(NamedColors.DarkBlue, new Rectangle(0 * scaleX, 40, 100 * scaleX, 20* scaleY)); + img.Fill(NamedColors.HotPink, new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY), new ImageSharp.GraphicsOptions(true) { BlenderMode = mode }); @@ -71,7 +76,32 @@ namespace ImageSharp.Tests.Drawing TPixel pixel = default(TPixel); pixel.PackFromVector4(c); - img.Fill(pixel, new Rectangle(40, 0, 20, 100), new ImageSharp.GraphicsOptions(true) + img.Fill(pixel, new SixLabors.Shapes.Ellipse(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY), new ImageSharp.GraphicsOptions(true) + { + BlenderMode = mode + }); + img.DebugSave(provider, new { mode }); + } + } + + + + [Theory] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] + public void DrawBlendedValues_doldidEllips(TestImageProvider provider, PixelBlenderMode mode) + where TPixel : struct, IPixel + { + using (var img = provider.GetImage()) + { + var scaleX = (img.Width / 100); + var scaleY = (img.Height / 100); + img.Fill(NamedColors.DarkBlue, new Rectangle(0 * scaleX, 40* scaleY, 100 * scaleX, 20 * scaleY)); + //img.Fill(NamedColors.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY), new ImageSharp.GraphicsOptions(true) + //{ + // BlenderMode = mode + //}); + + img.Fill(NamedColors.Black, new SixLabors.Shapes.Ellipse(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY), new ImageSharp.GraphicsOptions(true) { BlenderMode = mode });