Browse Source

Span.CopyTo(...) semantics for bulk Vecto4 conversion in PixelOperations

pull/744/head
Anton Firszov 7 years ago
parent
commit
ebff0a51e1
  1. 3
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
  2. 12
      src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs
  3. 25
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs
  4. 20
      src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs
  5. 28
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  6. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  7. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  8. 4
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
  9. 2
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs
  10. 2
      src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
  11. 2
      src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs
  12. 4
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  13. 10
      tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
  14. 4
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

3
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs

@ -159,7 +159,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
Span<TPixel> destRow = destination.GetPixelRowSpan(yy);
PixelOperations<TPixel>.Instance.FromVector4(this.rgbaBuffer.GetSpan(), destRow, destination.Width);
// TODO: Investigate if slicing is actually necessary
PixelOperations<TPixel>.Instance.FromVector4(this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow);
}
}
}

12
src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs

@ -93,12 +93,12 @@ namespace SixLabors.ImageSharp.PixelFormats
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(background, backgroundSpan, destination.Length);
PixelOperations<TPixelSrc>.Instance.ToScaledVector4(source, sourceSpan, destination.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(background, backgroundSpan);
PixelOperations<TPixelSrc>.Instance.ToScaledVector4(source, sourceSpan);
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount);
PixelOperations<TPixel>.Instance.FromScaledVector4(destinationSpan, destination, destination.Length);
PixelOperations<TPixel>.Instance.FromScaledVector4(destinationSpan, destination);
}
}
@ -127,12 +127,12 @@ namespace SixLabors.ImageSharp.PixelFormats
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(background, backgroundSpan, destination.Length);
PixelOperations<TPixelSrc>.Instance.ToScaledVector4(source, sourceSpan, destination.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(background, backgroundSpan);
PixelOperations<TPixelSrc>.Instance.ToScaledVector4(source, sourceSpan);
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount);
PixelOperations<TPixel>.Instance.FromScaledVector4(destinationSpan, destination, destination.Length);
PixelOperations<TPixel>.Instance.FromScaledVector4(destinationSpan, destination);
}
}
}

25
src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs

@ -19,13 +19,11 @@ namespace SixLabors.ImageSharp.PixelFormats
internal partial class PixelOperations : PixelOperations<Rgba32>
{
/// <inheritdoc />
internal override void ToVector4(ReadOnlySpan<Rgba32> sourceColors, Span<Vector4> destinationVectors, int count)
internal override void ToVector4(ReadOnlySpan<Rgba32> sourceColors, Span<Vector4> destinationVectors)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destinationVectors, count, nameof(destinationVectors));
Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors));
sourceColors = sourceColors.Slice(0, count);
destinationVectors = destinationVectors.Slice(0, count);
destinationVectors = destinationVectors.Slice(0, sourceColors.Length);
SimdUtils.BulkConvertByteToNormalizedFloat(
MemoryMarshal.Cast<Rgba32, byte>(sourceColors),
@ -33,12 +31,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
internal override void FromVector4(ReadOnlySpan<Vector4> sourceVectors, Span<Rgba32> destinationColors, int count)
internal override void FromVector4(ReadOnlySpan<Vector4> sourceVectors, Span<Rgba32> destinationColors)
{
GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count);
Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
sourceVectors = sourceVectors.Slice(0, count);
destinationColors = destinationColors.Slice(0, count);
destinationColors = destinationColors.Slice(0, sourceVectors.Length);
SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(
MemoryMarshal.Cast<Vector4, float>(sourceVectors),
@ -46,15 +43,17 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
internal override void ToScaledVector4(ReadOnlySpan<Rgba32> sourceColors, Span<Vector4> destinationVectors, int count)
internal override void ToScaledVector4(ReadOnlySpan<Rgba32> sourceColors, Span<Vector4> destinationVectors)
{
this.ToVector4(sourceColors, destinationVectors, count);
this.ToVector4(sourceColors, destinationVectors);
}
/// <inheritdoc />
internal override void FromScaledVector4(ReadOnlySpan<Vector4> sourceVectors, Span<Rgba32> destinationColors, int count)
internal override void FromScaledVector4(
ReadOnlySpan<Vector4> sourceVectors,
Span<Rgba32> destinationColors)
{
this.FromVector4(sourceVectors, destinationColors, count);
this.FromVector4(sourceVectors, destinationColors);
}
}
}

20
src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs

@ -18,23 +18,27 @@ namespace SixLabors.ImageSharp.PixelFormats
internal class PixelOperations : PixelOperations<RgbaVector>
{
/// <inheritdoc />
internal override void FromScaledVector4(ReadOnlySpan<Vector4> sourceVectors, Span<RgbaVector> destinationColors, int count)
internal override void FromScaledVector4(
ReadOnlySpan<Vector4> sourceVectors,
Span<RgbaVector> destinationColors)
{
GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count);
Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
MemoryMarshal.Cast<Vector4, RgbaVector>(sourceVectors).Slice(0, count).CopyTo(destinationColors);
MemoryMarshal.Cast<Vector4, RgbaVector>(sourceVectors).CopyTo(destinationColors);
}
/// <inheritdoc />
internal override void ToScaledVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destinationVectors, int count)
=> this.ToVector4(sourceColors, destinationVectors, count);
internal override void ToScaledVector4(
ReadOnlySpan<RgbaVector> sourceColors,
Span<Vector4> destinationVectors)
=> this.ToVector4(sourceColors, destinationVectors);
/// <inheritdoc />
internal override void ToVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destinationVectors, int count)
internal override void ToVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destinationVectors)
{
GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count);
Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors));
MemoryMarshal.Cast<RgbaVector, Vector4>(sourceColors).Slice(0, count).CopyTo(destinationVectors);
MemoryMarshal.Cast<RgbaVector, Vector4>(sourceColors).CopyTo(destinationVectors);
}
}
}

28
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

@ -26,15 +26,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="sourceVectors">The <see cref="Span{T}"/> to the source vectors.</param>
/// <param name="destinationColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void FromVector4(ReadOnlySpan<Vector4> sourceVectors, Span<TPixel> destinationColors, int count)
internal virtual void FromVector4(ReadOnlySpan<Vector4> sourceVectors, Span<TPixel> destinationColors)
{
GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count);
Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors);
ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors);
for (int i = 0; i < count; i++)
for (int i = 0; i < sourceVectors.Length; i++)
{
ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i);
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
@ -47,15 +46,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destinationVectors">The <see cref="Span{T}"/> to the destination vectors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToVector4(ReadOnlySpan<TPixel> sourceColors, Span<Vector4> destinationVectors, int count)
internal virtual void ToVector4(ReadOnlySpan<TPixel> sourceColors, Span<Vector4> destinationVectors)
{
GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count);
Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors));
ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors);
ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors);
for (int i = 0; i < count; i++)
for (int i = 0; i < sourceColors.Length; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
ref Vector4 dp = ref Unsafe.Add(ref destRef, i);
@ -68,15 +66,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="sourceVectors">The <see cref="Span{T}"/> to the source vectors.</param>
/// <param name="destinationColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void FromScaledVector4(ReadOnlySpan<Vector4> sourceVectors, Span<TPixel> destinationColors, int count)
internal virtual void FromScaledVector4(ReadOnlySpan<Vector4> sourceVectors, Span<TPixel> destinationColors)
{
GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count);
Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors);
ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors);
for (int i = 0; i < count; i++)
for (int i = 0; i < sourceVectors.Length; i++)
{
ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i);
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
@ -89,15 +86,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destinationVectors">The <see cref="Span{T}"/> to the destination vectors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToScaledVector4(ReadOnlySpan<TPixel> sourceColors, Span<Vector4> destinationVectors, int count)
internal virtual void ToScaledVector4(ReadOnlySpan<TPixel> sourceColors, Span<Vector4> destinationVectors)
{
GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count);
Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors));
ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors);
ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors);
for (int i = 0; i < count; i++)
for (int i = 0; i < sourceColors.Length; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
ref Vector4 dp = ref Unsafe.Add(ref destRef, i);

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -75,14 +75,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan, length);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan);
for (int x = 0; x < width; x++)
{
DenseMatrixUtils.Convolve2D(in matrixY, in matrixX, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX);
}
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan, length);
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan);
}
});

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -93,14 +93,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan, length);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan);
for (int x = 0; x < width; x++)
{
DenseMatrixUtils.Convolve(in matrix, sourcePixels, vectorSpan, y, x, maxY, maxX, startX);
}
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan, length);
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan);
}
});
}

4
src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs

@ -59,14 +59,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan, length);
PixelOperations<TPixel>.Instance.ToVector4(targetRowSpan, vectorSpan);
for (int x = 0; x < width; x++)
{
DenseMatrixUtils.Convolve(in matrix, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX);
}
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan, length);
PixelOperations<TPixel>.Instance.FromVector4(vectorSpan, targetRowSpan);
}
});

2
src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs

@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
{
this.Palette = palette ?? throw new ArgumentNullException(nameof(palette));
this.paletteVector = new Vector4[this.Palette.Length];
PixelOperations<TPixel>.Instance.ToScaledVector4(this.Palette, this.paletteVector, this.Palette.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(this.Palette, this.paletteVector);
}
/// <summary>

2
src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs

@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
// Collect the palette. Required before the second pass runs.
TPixel[] palette = this.GetPalette();
this.paletteVector = new Vector4[palette.Length];
PixelOperations<TPixel>.Instance.ToScaledVector4(palette, this.paletteVector, palette.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(palette, this.paletteVector);
var quantizedFrame = new QuantizedFrame<TPixel>(image.MemoryAllocator, width, height, palette);
if (this.Dither)

2
src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs

@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
Guard.MustBeBetweenOrEqualTo(colors.Length, 1, 256, nameof(colors));
this.palette = colors;
this.paletteVector = new Vector4[this.palette.Length];
PixelOperations<TPixel>.Instance.ToScaledVector4(this.palette, this.paletteVector, this.palette.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(this.palette, this.paletteVector);
}
/// <inheritdoc/>

4
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -257,7 +257,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
Span<Vector4> tempRowSpan = tempRowBuffer.Span;
PixelOperations<TPixel>.Instance.ToVector4(sourceRow, tempRowSpan, sourceRow.Length);
PixelOperations<TPixel>.Instance.ToVector4(sourceRow, tempRowSpan);
Vector4Utils.Premultiply(tempRowSpan);
ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y];
@ -309,7 +309,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
Span<TPixel> targetRowSpan = destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.FromVector4(tempRowSpan, targetRowSpan, tempRowSpan.Length);
PixelOperations<TPixel>.Instance.FromVector4(tempRowSpan, targetRowSpan);
}
});
}

10
tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs

@ -269,7 +269,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
{
this.Measure(
times,
() => PixelOperations<Rgba32>.Instance.ToVector4(source.GetSpan(), dest.GetSpan(), count));
() => PixelOperations<Rgba32>.Instance.ToVector4(source.GetSpan(), dest.GetSpan()));
}
}
}
@ -367,7 +367,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
TestOperation(
source,
expected,
(s, d) => Operations.FromVector4(s, d.GetSpan(), count)
(s, d) => Operations.FromVector4(s, d.GetSpan())
);
}
@ -381,7 +381,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
TestOperation(
source,
expected,
(s, d) => Operations.FromScaledVector4(s, d.GetSpan(), count)
(s, d) => Operations.FromScaledVector4(s, d.GetSpan())
);
}
@ -417,7 +417,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
TestOperation(
source,
expected,
(s, d) => Operations.ToVector4(s, d.GetSpan(), count)
(s, d) => Operations.ToVector4(s, d.GetSpan())
);
}
@ -431,7 +431,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
TestOperation(
source,
expected,
(s, d) => Operations.ToScaledVector4(s, d.GetSpan(), count)
(s, d) => Operations.ToScaledVector4(s, d.GetSpan())
);
}

4
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests
{
Span<TPixel> pixelSpan = frame.GetPixelSpan();
PixelOperations<TPixel>.Instance.ToScaledVector4(pixelSpan, tempSpan, pixelSpan.Length);
PixelOperations<TPixel>.Instance.ToScaledVector4(pixelSpan, tempSpan);
for (int i = 0; i < tempSpan.Length; i++)
{
@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests
v.W = 1F;
}
PixelOperations<TPixel>.Instance.FromScaledVector4(tempSpan, pixelSpan, pixelSpan.Length);
PixelOperations<TPixel>.Instance.FromScaledVector4(tempSpan, pixelSpan);
}
}
});

Loading…
Cancel
Save