mirror of https://github.com/SixLabors/ImageSharp
Browse Source
* Added new properties to ImageProcessor<TPixel> * Fixed constructors for convolution processors * Fixed constructors for binarization processors * Fixed constructor for dithering processor * Fixed constructors for effects processors * Fixed constructor for filter processor * Fixed constructor for normalization processor * Fixed constructors for overlay processors * Fixed constructor for quantization processor * Fixed constructors for transforms processors * Updated CreatePixelSpecificProcessor<TPixel> definition * Fixed convolution processors creation * Fixed leftover dithering processor constructor * Fixed another leftover dithering processor constructor * Fixed dithering processors creation * Fixed effects processors creation * Fixed filters processor * Fixed normalization processors creation * Fixed overlays processors creation * Fixed quantizer processor creation * Fixed constructors for some remaining processors * Fixed transform processors creation * ImageProcessor class refactored * Renamed some parameters * Convolution processors refactored * Refactored filters and dithering processors * Refactored normalization processors * Overlays processors refactored * Renamed some parameters * CloningImageProcessor class refactored * Transforms processors refactored * Updated DefaultImageProcessingContext class * Src builds, tests still require updating. * Fix tests * Removed unnecessary local variableaf/merge-core
committed by
James Jackson-South
101 changed files with 961 additions and 891 deletions
@ -1,176 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Numerics; |
|||
|
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.ParallelUtils; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing.Processors; |
|||
using SixLabors.ImageSharp.Processing.Processors.Overlays; |
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks |
|||
{ |
|||
using CoreSize = SixLabors.Primitives.Size; |
|||
|
|||
public class Glow : BenchmarkBase |
|||
{ |
|||
private GlowProcessor bulk; |
|||
|
|||
private GlowProcessorParallel<Rgba32> parallel; |
|||
|
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
this.bulk = new GlowProcessor(Color.Beige, 800 * .5f, GraphicsOptions.Default); |
|||
this.parallel = new GlowProcessorParallel<Rgba32>(Color.Beige) { Radius = 800 * .5f, }; |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp Glow - Bulk")] |
|||
public CoreSize GlowBulk() |
|||
{ |
|||
using (var image = new Image<Rgba32>(800, 800)) |
|||
{ |
|||
this.bulk.Apply(image, image.Bounds()); |
|||
return new CoreSize(image.Width, image.Height); |
|||
} |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp Glow - Parallel")] |
|||
public CoreSize GLowSimple() |
|||
{ |
|||
using (var image = new Image<Rgba32>(800, 800)) |
|||
{ |
|||
this.parallel.Apply(image, image.Bounds()); |
|||
return new CoreSize(image.Width, image.Height); |
|||
} |
|||
} |
|||
|
|||
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 OnFrameApply( |
|||
ImageFrame<TPixel> source, |
|||
Rectangle sourceRectangle, |
|||
Configuration configuration) |
|||
{ |
|||
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); |
|||
float maxDistance = this.Radius > 0 |
|||
? Math.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 (IMemoryOwner<TPixel> rowColors = Configuration.Default.MemoryAllocator.Allocate<TPixel>(width)) |
|||
{ |
|||
Buffer2D<TPixel> sourcePixels = source.PixelBuffer; |
|||
rowColors.GetSpan().Fill(glowColor); |
|||
|
|||
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); |
|||
ParallelHelper.IterateRows( |
|||
workingRect, |
|||
configuration, |
|||
rows => |
|||
{ |
|||
for (int y = rows.Min; y < rows.Max; 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; |
|||
packed.FromVector4( |
|||
PremultipliedLerp( |
|||
sourceColor, |
|||
glowColor.ToVector4(), |
|||
1 - (.95F * (distance / maxDistance)))); |
|||
sourcePixels[offsetX, offsetY] = packed; |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public static Vector4 PremultipliedLerp(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
amount = amount.Clamp(0, 1); |
|||
|
|||
// Sanitize on zero alpha
|
|||
if (Math.Abs(backdrop.W) < Constants.Epsilon) |
|||
{ |
|||
source.W *= amount; |
|||
return source; |
|||
} |
|||
|
|||
if (Math.Abs(source.W) < Constants.Epsilon) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
// Premultiply the source vector.
|
|||
// Oddly premultiplying the background vector creates dark outlines when pixels
|
|||
// Have low alpha values.
|
|||
source = new Vector4(source.X, source.Y, source.Z, 1) * (source.W * amount); |
|||
|
|||
// This should be implementing the following formula
|
|||
// https://en.wikipedia.org/wiki/Alpha_compositing
|
|||
// Vout = Vs + Vb (1 - Vsa)
|
|||
// Aout = Vsa + Vsb (1 - Vsa)
|
|||
var inverseW = new Vector3(1 - source.W); |
|||
var xyzB = new Vector3(backdrop.X, backdrop.Y, backdrop.Z); |
|||
var xyzS = new Vector3(source.X, source.Y, source.Z); |
|||
|
|||
return new Vector4(xyzS + (xyzB * inverseW), source.W + (backdrop.W * (1 - source.W))); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue