/// <summary> /// Provides a configured LinearGradient that can be used in combination with a GradientImageSource to provide a mask for the LensBlurEffect. /// It will expect the LensBlur will be blurred with 1 kernel when the double is different from None. /// </summary> /// <param name="ellipse">The band that represents the focus area in the image. Pixels within this band won't be blurred. /// Areas outside of the area will be progressively more blurred as the distance from the focus band increases.</param> /// <param name="strength">Strength of the blur.</param> /// <returns>A LinearGradient that can be used in combination with a GradientImageSource to be used by LensBlur.</returns> public static RadialGradient GenerateGradient(FocusEllipse ellipse, KernelGenerator kernelGenerator) { if (kernelGenerator.GetKernelBands().Count == 0) { return(null); } EllipseRadius maxBlurRadius = null; if ((ellipse.Radius.X < minDiffBetweenStops) && (ellipse.Radius.Y < minDiffBetweenStops)) { maxBlurRadius = new EllipseRadius(minDiffBetweenStops, minDiffBetweenStops); } else { double factor = 0.9; bool widthGtHight = ellipse.Radius.X > ellipse.Radius.Y; if (widthGtHight) { maxBlurRadius = new EllipseRadius(factor, factor * ellipse.Radius.Y / ellipse.Radius.X); } else { maxBlurRadius = new EllipseRadius(factor * ellipse.Radius.X / ellipse.Radius.Y, factor); } } var gradient = new RadialGradient(ellipse.Center, maxBlurRadius); SetGradientStops(gradient, ellipse, maxBlurRadius, kernelGenerator); return(gradient); }
/// <summary> /// Provides a configured LinearGradient that can be used in combination with a GradientImageSource to provide a mask for the LensBlurEffect. /// It will expect the LensBlur will be blurred with 1 kernel when the double is different from None. /// </summary> /// <param name="ellipse">The band that represents the focus area in the image. Pixels within this band won't be blurred. /// Areas outside of the area will be progressively more blurred as the distance from the focus band increases.</param> /// <param name="strength">Strength of the blur.</param> /// <returns>A LinearGradient that can be used in combination with a GradientImageSource to be used by LensBlur.</returns> public static RadialGradient GenerateGradient(FocusEllipse ellipse, KernelGenerator kernelGenerator) { if (kernelGenerator.GetKernelBands().Count == 0) { return null; } EllipseRadius maxBlurRadius = null; if ((ellipse.Radius.X < minDiffBetweenStops) && (ellipse.Radius.Y < minDiffBetweenStops)) { maxBlurRadius = new EllipseRadius(minDiffBetweenStops, minDiffBetweenStops); } else { double factor = 0.9; bool widthGtHight = ellipse.Radius.X > ellipse.Radius.Y; if (widthGtHight) { maxBlurRadius = new EllipseRadius(factor, factor * ellipse.Radius.Y / ellipse.Radius.X); } else { maxBlurRadius = new EllipseRadius(factor * ellipse.Radius.X / ellipse.Radius.Y, factor); } } var gradient = new RadialGradient(ellipse.Center, maxBlurRadius); SetGradientStops(gradient, ellipse, maxBlurRadius, kernelGenerator); return gradient; }
private static void SetGradientStops(RadialGradient gradient, FocusEllipse ellipse, EllipseRadius maxBlurRadius, KernelGenerator kernelGenerator) { var stops = new List<GradientStop>(); double firstStopOffset; if (maxBlurRadius.X > minDiffBetweenStops) { firstStopOffset = ellipse.Radius.X / maxBlurRadius.X; //Add the focus area at the center of the ellipse. stops.Add(new GradientStop() { Color = Color.FromArgb(255, 0, 0, 0), Offset = 0 }); stops.Add(new GradientStop() { Color = Color.FromArgb(255, 0, 0, 0), Offset = firstStopOffset }); } else { firstStopOffset = minDiffBetweenStops; } double sumOfBandWidths = kernelGenerator.GetKernelBands().Select(band => band.Width).Sum(); var currentStopOffset = firstStopOffset + minDiffBetweenStops; var kernelBands = kernelGenerator.GetKernelBands(); byte kernelIndex = 0; foreach (var band in kernelBands) { kernelIndex++; stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset }); currentStopOffset = currentStopOffset + (band.Width / sumOfBandWidths) * (1 - firstStopOffset) * FocusToBlurTransitionWidth; } stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset }); var validStops = EnsureMinDiffBetweenPoints(stops); gradient.Stops = validStops.ToArray(); }
private protected override void UpdatePaintCore(SKPaint paint, SKRect bounds) { var center = EllipseCenter.ToSKPoint(); var gradientOrigin = EllipseCenter.ToSKPoint() + GradientOriginOffset.ToSKPoint(); var radius = EllipseRadius.ToSKPoint(); var transform = CreateTransformMatrix(bounds); // Transform the points into absolute coordinates. if (MappingMode == CompositionMappingMode.Relative) { // If the point are provided relative they must be multiplied by bounds. center.X *= bounds.Width; center.Y *= bounds.Height; gradientOrigin.X *= bounds.Width; gradientOrigin.Y *= bounds.Height; radius.X *= bounds.Width; radius.Y *= bounds.Height; } // Translate gradient points by bounds offset. center.X += bounds.Left; center.Y += bounds.Top; gradientOrigin.X += bounds.Left; gradientOrigin.Y += bounds.Top; // // SkiaSharp does not allow explicit definition of RadiusX and RadiusY. // Compute transformation matrix to compensate. ComputeRadiusAndScale(center, radius.X, radius.Y, out float gradientRadius, out SKMatrix matrix); // Clean up old shader if (paint.Shader != null) { paint.Shader.Dispose(); paint.Shader = null; } if (gradientRadius > 0) { // Create radial gradient shader. SKShader shader = SKShader.CreateTwoPointConicalGradient( /* start */ gradientOrigin, /* start radius */ 0, /* end */ center, /* gradient radius */ gradientRadius, Colors, ColorPositions, TileMode, transform.PreConcat(matrix)); paint.Shader = shader; paint.Color = SKColors.Black.WithAlpha((byte)(Compositor.CurrentOpacity * 255)); } else { // With radius equal to 0, SkiaSharp does not draw anything. // But we expect last gradient color. // If there are no gradient stops available, use transparent. SKColor color = SKColors.Transparent; if (Colors !.Length > 0) { color = Colors[Colors.Length - 1]; } double alpha = (color.Alpha / 255.0) * Compositor.CurrentOpacity; paint.Color = color.WithAlpha((byte)(alpha * 255)); } }
public FocusEllipse(double x, double y, double xRadius, double yRadius) { Center = new Point(x, y); Radius = new EllipseRadius(xRadius, yRadius); }
/// <summary> /// Creates and initialized a new FocusEllipse with specified center and radius. /// </summary> /// <param name="center">The center of the ellipse. Expressed in the unit coordinate space of the image area, /// i.e., the top left corner of the image is at (0.0), and the bottom right corner is at (1, 1).</param> /// <param name="radius">The radius of the ellipse. Expressed in the unit coordinate space of the image area, /// i.e., the top left corner of the image is at (0.0), and the bottom right corner is at (1, 1).</param> public FocusEllipse(Point center, EllipseRadius radius) { Center = center; Radius = radius; }
private static void SetGradientStops(RadialGradient gradient, FocusEllipse ellipse, EllipseRadius maxBlurRadius, KernelGenerator kernelGenerator) { var stops = new List <GradientStop>(); double firstStopOffset; if (maxBlurRadius.X > minDiffBetweenStops) { firstStopOffset = ellipse.Radius.X / maxBlurRadius.X; //Add the focus area at the center of the ellipse. stops.Add(new GradientStop() { Color = Color.FromArgb(255, 0, 0, 0), Offset = 0 }); stops.Add(new GradientStop() { Color = Color.FromArgb(255, 0, 0, 0), Offset = firstStopOffset }); } else { firstStopOffset = minDiffBetweenStops; } double sumOfBandWidths = kernelGenerator.GetKernelBands().Select(band => band.Width).Sum(); var currentStopOffset = firstStopOffset + minDiffBetweenStops; var kernelBands = kernelGenerator.GetKernelBands(); byte kernelIndex = 0; foreach (var band in kernelBands) { kernelIndex++; stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset }); currentStopOffset = currentStopOffset + (band.Width / sumOfBandWidths) * (1 - firstStopOffset) * FocusToBlurTransitionWidth; } stops.Add(new GradientStop() { Color = Color.FromArgb(255, kernelIndex, kernelIndex, kernelIndex), Offset = currentStopOffset }); var validStops = EnsureMinDiffBetweenPoints(stops); gradient.Stops = validStops.ToArray(); }