/// <summary> /// Initializes a new instance of the <see cref="RecolorBrushApplicator{TPixel}" /> class. /// </summary> /// <param name="configuration">The configuration instance to use when performing operations.</param> /// <param name="options">The options</param> /// <param name="source">The source image.</param> /// <param name="sourceColor">Color of the source.</param> /// <param name="targetColor">Color of the target.</param> /// <param name="threshold">The threshold .</param> public RecolorBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame <TPixel> source, TPixel sourceColor, TPixel targetColor, float threshold) : base(configuration, options, source) { this.sourceColor = sourceColor.ToVector4(); this.targetColorPixel = targetColor; // Lets hack a min max extremes for a color space by letting the IPackedPixel clamp our values to something in the correct spaces :) var maxColor = default(TPixel); maxColor.FromVector4(new Vector4(float.MaxValue)); var minColor = default(TPixel); minColor.FromVector4(new Vector4(float.MinValue)); this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold; this.scalineWidth = source.Width; this.allocator = configuration.MemoryAllocator; this.blenderBuffers = new ThreadLocalBlenderBuffers <TPixel>(configuration.MemoryAllocator, source.Width); }
public void Dispose_ReturnsAllBuffers(bool amountBufferOnly, int threadCount) { var buffers = new ThreadLocalBlenderBuffers <Rgb24>(this.memoryAllocator, 100, amountBufferOnly); void RunThread() { buffers.AmountSpan[0] = 42; } Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread(RunThread); threads[i].Start(); } foreach (Thread thread in threads) { thread.Join(); } buffers.Dispose(); int expectedReturnCount = amountBufferOnly ? threadCount : 2 * threadCount; Assert.Equal(expectedReturnCount, this.memoryAllocator.ReturnLog.Count); }
/// <summary> /// Initializes a new instance of the <see cref="SolidBrushApplicator{TPixel}"/> class. /// </summary> /// <param name="configuration">The configuration instance to use when performing operations.</param> /// <param name="options">The graphics options.</param> /// <param name="source">The source image.</param> /// <param name="color">The color.</param> public SolidBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame <TPixel> source, TPixel color) : base(configuration, options, source) { this.colors = configuration.MemoryAllocator.Allocate <TPixel>(source.Width); this.colors.Memory.Span.Fill(color); this.scalineWidth = source.Width; this.allocator = configuration.MemoryAllocator; // The threadlocal value is lazily invoked so there is no need to optionally create the type. this.blenderBuffers = new ThreadLocalBlenderBuffers <TPixel>(configuration.MemoryAllocator, source.Width, true); }
/// <summary> /// Initializes a new instance of the <see cref="GradientBrushApplicator{TPixel}"/> class. /// </summary> /// <param name="configuration">The configuration instance to use when performing operations.</param> /// <param name="options">The graphics options.</param> /// <param name="target">The target image.</param> /// <param name="colorStops">An array of color stops sorted by their position.</param> /// <param name="repetitionMode">Defines if and how the gradient should be repeated.</param> protected GradientBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame <TPixel> target, ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(configuration, options, target) { // TODO: requires colorStops to be sorted by position. // Use Array.Sort with a custom comparer. this.colorStops = colorStops; this.repetitionMode = repetitionMode; this.scalineWidth = target.Width; this.allocator = configuration.MemoryAllocator; this.blenderBuffers = new ThreadLocalBlenderBuffers <TPixel>(this.allocator, this.scalineWidth); }
/// <summary> /// Initializes a new instance of the <see cref="PathGradientBrushApplicator{TPixel}"/> class. /// </summary> /// <param name="configuration">The configuration instance to use when performing operations.</param> /// <param name="options">The graphics options.</param> /// <param name="source">The source image.</param> /// <param name="edges">Edges of the polygon.</param> /// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param> /// <param name="hasSpecialCenterColor">Whether the center color is different from a smooth gradient between the edges.</param> public PathGradientBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame <TPixel> source, IList <Edge> edges, Color centerColor, bool hasSpecialCenterColor) : base(configuration, options, source) { this.edges = edges; Vector2[] points = edges.Select(s => s.Start).ToArray(); this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count; this.centerColor = (Vector4)centerColor; this.hasSpecialCenterColor = hasSpecialCenterColor; this.centerPixel = centerColor.ToPixel <TPixel>(); this.maxDistance = points.Select(p => p - this.center).Max(d => d.Length()); this.transparentPixel = Color.Transparent.ToPixel <TPixel>(); this.blenderBuffers = new ThreadLocalBlenderBuffers <TPixel>(configuration.MemoryAllocator, source.Width); }
public void CreatesPerThreadUniqueInstances() { using var buffers = new ThreadLocalBlenderBuffers <Rgb24>(this.memoryAllocator, 100); var allSetSemaphore = new SemaphoreSlim(2); var thread1 = new Thread(() => { Span <float> ams = buffers.AmountSpan; Span <Rgb24> overlays = buffers.OverlaySpan; ams[0] = 10; overlays[0] = new Rgb24(10, 10, 10); allSetSemaphore.Release(1); allSetSemaphore.Wait(); Assert.Equal(10, buffers.AmountSpan[0]); Assert.Equal(10, buffers.OverlaySpan[0].R); }); var thread2 = new Thread(() => { Span <float> ams = buffers.AmountSpan; Span <Rgb24> overlays = buffers.OverlaySpan; ams[0] = 20; overlays[0] = new Rgb24(20, 20, 20); allSetSemaphore.Release(1); allSetSemaphore.Wait(); Assert.Equal(20, buffers.AmountSpan[0]); Assert.Equal(20, buffers.OverlaySpan[0].R); }); thread1.Start(); thread2.Start(); thread1.Join(); thread2.Join(); }