// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Processing.Transforms.Processors { /// /// Points to a collection of of weights allocated in . /// internal struct WeightsWindow { /// /// The local left index position /// public int Left; /// /// The length of the weights window /// public int Length; /// /// The index in the destination buffer /// private readonly int flatStartIndex; /// /// The buffer containing the weights values. /// private readonly IBuffer buffer; /// /// Initializes a new instance of the struct. /// /// The destination index in the buffer /// The local left index /// The span /// The length of the window [MethodImpl(MethodImplOptions.AggressiveInlining)] internal WeightsWindow(int index, int left, Buffer2D buffer, int length) { this.flatStartIndex = (index * buffer.Width) + left; this.Left = left; this.buffer = buffer.Buffer; this.Length = length; } /// /// Gets a reference to the first item of the window. /// /// The reference to the first item of the window [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref float GetStartReference() { Span span = this.buffer.Span; return ref span[this.flatStartIndex]; } /// /// Gets the span representing the portion of the that this window covers /// /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetWindowSpan() => this.buffer.Slice(this.flatStartIndex, this.Length); /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. /// /// The input span of vectors /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeWeightedRowSum(Span rowSpan, int sourceX) { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left + sourceX); // Destination color components Vector4 result = Vector4.Zero; for (int i = 0; i < this.Length; i++) { float weight = Unsafe.Add(ref horizontalValues, i); Vector4 v = Unsafe.Add(ref vecPtr, i); result += v.Premultiply() * weight; } return result; } /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. /// Applies to all input vectors. /// /// The input span of vectors /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeExpandedWeightedRowSum(Span rowSpan, int sourceX) { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left + sourceX); // Destination color components Vector4 result = Vector4.Zero; for (int i = 0; i < this.Length; i++) { float weight = Unsafe.Add(ref horizontalValues, i); Vector4 v = Unsafe.Add(ref vecPtr, i); result += v.Premultiply().Expand() * weight; } return result.UnPremultiply(); } /// /// Computes the sum of vectors in 'firstPassPixels' at a row pointed by 'x', /// weighted by weight values, pointed by this instance. /// /// The buffer of input vectors in row first order /// The row position /// The source column position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeWeightedColumnSum(Buffer2D firstPassPixels, int x, int sourceY) { ref float verticalValues = ref this.GetStartReference(); int left = this.Left; // Destination color components Vector4 result = Vector4.Zero; for (int i = 0; i < this.Length; i++) { float yw = Unsafe.Add(ref verticalValues, i); int index = left + i + sourceY; result += firstPassPixels[x, index] * yw; } return result.UnPremultiply(); } } }