diff --git a/src/ImageProcessor/Colors/Color.cs b/src/ImageProcessor/Colors/Color.cs index 639612f4f..9dbf9da00 100644 --- a/src/ImageProcessor/Colors/Color.cs +++ b/src/ImageProcessor/Colors/Color.cs @@ -353,7 +353,8 @@ namespace ImageProcessor amount = amount.Clamp(0f, 1f); // Premultiplied. - return (from * (1 - amount)) + to; + return from + (to - from) * amount; + //return (from * (1 - amount)) + to; } /// diff --git a/src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs b/src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs index d8f4cd8e5..c6ea9ef30 100644 --- a/src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs +++ b/src/ImageProcessor/Filters/ColorMatrix/Lomograph.cs @@ -22,5 +22,11 @@ namespace ImageProcessor.Filters M42 = .0f, M43 = -.08f }; + + /// + protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) + { + new Vignette { Color = new Color(0, 10 / 255f, 0) }.Apply(target, target, targetRectangle); + } } } diff --git a/src/ImageProcessor/Filters/ColorMatrix/Polaroid.cs b/src/ImageProcessor/Filters/ColorMatrix/Polaroid.cs index fb14c584c..d6c91ffda 100644 --- a/src/ImageProcessor/Filters/ColorMatrix/Polaroid.cs +++ b/src/ImageProcessor/Filters/ColorMatrix/Polaroid.cs @@ -28,5 +28,12 @@ namespace ImageProcessor.Filters M42 = -0.05f, M43 = -0.05f }; + + /// + protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) + { + new Vignette { Color = new Color(102 / 255f, 34 / 255f, 0) }.Apply(target, target, targetRectangle); + new Glow { Color = new Color(1, 153 / 255f, 102 / 255f) }.Apply(target, target, targetRectangle); + } } } diff --git a/src/ImageProcessor/Filters/Glow.cs b/src/ImageProcessor/Filters/Glow.cs new file mode 100644 index 000000000..29bba7cdb --- /dev/null +++ b/src/ImageProcessor/Filters/Glow.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessor.Filters +{ + using System; + using System.Numerics; + using System.Threading.Tasks; + + /// + /// Creates a glow effect on the image + /// + public class Glow : ParallelImageProcessor + { + /// + /// Gets or sets the vignette color to apply. + /// + public Color Color { get; set; } = Color.White; + + /// + /// Gets or sets the the x-radius. + /// + public float RadiusX { get; set; } + + /// + /// Gets or sets the the y-radius. + /// + public float RadiusY { get; set; } + + /// + protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) + { + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + Color color = this.Color; + Vector2 centre = Rectangle.Center(targetRectangle); + float rX = this.RadiusX > 0 ? this.RadiusX : targetRectangle.Width / 2f; + float rY = this.RadiusY > 0 ? this.RadiusY : targetRectangle.Height / 2f; + float maxDistance = (float)Math.Sqrt(rX * rX + rY * rY); + + Parallel.For( + startY, + endY, + y => + { + for (int x = startX; x < endX; x++) + { + float distance = Vector2.Distance(centre, new Vector2(x, y)); + Color sourceColor = target[x, y]; + target[x, y] = Color.Lerp(color, sourceColor, 4f * distance / maxDistance); + } + }); + } + } +} + diff --git a/src/ImageProcessor/Filters/Vignette.cs b/src/ImageProcessor/Filters/Vignette.cs index 547308cc9..a309c4648 100644 --- a/src/ImageProcessor/Filters/Vignette.cs +++ b/src/ImageProcessor/Filters/Vignette.cs @@ -1,18 +1,19 @@ -namespace ImageProcessor.Filters +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessor.Filters { + using System; using System.Numerics; using System.Threading.Tasks; /// - /// Creates a vignette + /// Creates a vignette effect on the image /// public class Vignette : ParallelImageProcessor { - /// - /// Used to hold a copy of the target image. - /// - private readonly Image targetCopy = new Image(); - /// /// Gets or sets the vignette color to apply. /// @@ -28,26 +29,16 @@ /// public float RadiusY { get; set; } - /// - protected override void OnApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) - { - this.targetCopy.SetPixels(target.Width, target.Height, target.Pixels); - target.SetPixels(target.Width, target.Height, new float[target.Pixels.Length]); - } - /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { int startX = sourceRectangle.X; int endX = sourceRectangle.Right; - + Color color = this.Color; Vector2 centre = Rectangle.Center(targetRectangle); - int centerX = (int)centre.X; - int centerY = (int)centre.Y; float rX = this.RadiusX > 0 ? this.RadiusX : targetRectangle.Width / 2f; float rY = this.RadiusY > 0 ? this.RadiusY : targetRectangle.Height / 2f; - - Ellipse ellipse = new Ellipse(new Point(centerX, centerY), rX - 1, rY - 1); + float maxDistance = (float)Math.Sqrt(rX * rX + rY * rY); Parallel.For( startY, @@ -56,22 +47,12 @@ { for (int x = startX; x < endX; x++) { - if (!ellipse.Contains(x, y)) - { - target[x, y] = Color.Black; - } + float distance = Vector2.Distance(centre, new Vector2(x, y)); + Color sourceColor = target[x, y]; + target[x, y] = Color.Lerp(sourceColor, color, .9f * distance / maxDistance); } }); } - - /// - protected override void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) - { - new GuassianBlur(30).Apply(target, target, targetRectangle); - Image temp = new Image(this.targetCopy); - new Blend(target, 40).Apply(this.targetCopy, temp, targetRectangle); - target.SetPixels(temp.Width, temp.Height, this.targetCopy.Pixels); - } } } diff --git a/src/ImageProcessor/Numerics/Ellipse.cs b/src/ImageProcessor/Numerics/Ellipse.cs index 9bd340920..1f581e8d1 100644 --- a/src/ImageProcessor/Numerics/Ellipse.cs +++ b/src/ImageProcessor/Numerics/Ellipse.cs @@ -97,7 +97,7 @@ namespace ImageProcessor /// /// Determines if the specfied point is contained within the rectangular region defined by - /// this . + /// this . /// /// The x-coordinate of the given point. /// The y-coordinate of the given point.