mirror of https://github.com/SixLabors/ImageSharp
28 changed files with 351 additions and 258 deletions
@ -1,98 +0,0 @@ |
|||||
// <copyright file="GlowProcessor.cs" company="James Jackson-South">
|
|
||||
// Copyright (c) James Jackson-South and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
using ImageSharp.PixelFormats; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial glow effect an <see cref="Image{TPixel}"/>.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class GlowProcessorParallel<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="GlowProcessorParallel{TPixel}" /> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="color">The color or the glow.</param>
|
|
||||
public GlowProcessorParallel(TPixel color) |
|
||||
{ |
|
||||
this.GlowColor = color; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the glow color to apply.
|
|
||||
/// </summary>
|
|
||||
public TPixel GlowColor { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the the radius.
|
|
||||
/// </summary>
|
|
||||
public float Radius { get; set; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) |
|
||||
{ |
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
TPixel glowColor = this.GlowColor; |
|
||||
Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); |
|
||||
float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
int width = maxX - minX; |
|
||||
using (Buffer<TPixel> rowColors = new Buffer<TPixel>(width)) |
|
||||
using (PixelAccessor<TPixel> sourcePixels = source.Lock()) |
|
||||
{ |
|
||||
for (int i = 0; i < width; i++) |
|
||||
{ |
|
||||
rowColors[i] = glowColor; |
|
||||
} |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
this.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
int offsetY = y - startY; |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
int offsetX = x - startX; |
|
||||
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY)); |
|
||||
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4(); |
|
||||
TPixel packed = default(TPixel); |
|
||||
packed.PackFromVector4(Vector4BlendTransforms.PremultipliedLerp(sourceColor, glowColor.ToVector4(), 1 - (.95F * (distance / maxDistance)))); |
|
||||
sourcePixels[offsetX, offsetY] = packed; |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,56 @@ |
|||||
|
// <copyright file="DrawImageEffectTest.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageSharp.Tests.Drawing |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using ImageSharp.PixelFormats; |
||||
|
using Xunit; |
||||
|
|
||||
|
public class BlendedShapes |
||||
|
{ |
||||
|
public static IEnumerable<object[]> modes = ((PixelBlenderMode[])Enum.GetValues(typeof(PixelBlenderMode))) |
||||
|
.Select(x=> new object[] { x }); |
||||
|
|
||||
|
[Theory] |
||||
|
[WithBlankImages(nameof(modes), 100, 100, PixelTypes.StandardImageClass)] |
||||
|
public void DrawBlendedValues<TPixel>(TestImageProvider<TPixel> provider, PixelBlenderMode mode) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
using (var img = provider.GetImage()) |
||||
|
{ |
||||
|
img.Fill(NamedColors<TPixel>.DarkBlue, new Rectangle(0, 40, 100, 20)); |
||||
|
img.Fill(NamedColors<TPixel>.HotPink, new Rectangle(40, 0, 20, 100), new ImageSharp.GraphicsOptions(true) |
||||
|
{ |
||||
|
BlenderMode = mode |
||||
|
}); |
||||
|
img.DebugSave(provider, new { mode }); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithBlankImages(nameof(modes), 100, 100, PixelTypes.StandardImageClass)] |
||||
|
public void DrawBlendedValues_transparent<TPixel>(TestImageProvider<TPixel> provider, PixelBlenderMode mode) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
using (var img = provider.GetImage()) |
||||
|
{ |
||||
|
img.Fill(NamedColors<TPixel>.DarkBlue, new Rectangle(0, 40, 100, 20)); |
||||
|
img.Fill(NamedColors<TPixel>.HotPink, new Rectangle(20, 0, 40, 100), new ImageSharp.GraphicsOptions(true) |
||||
|
{ |
||||
|
BlenderMode = mode |
||||
|
}); |
||||
|
img.Fill(NamedColors<TPixel>.Transparent, new Rectangle(40, 0, 20, 100), new ImageSharp.GraphicsOptions(true) |
||||
|
{ |
||||
|
BlenderMode = mode |
||||
|
}); |
||||
|
img.DebugSave(provider, new { mode }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue