Browse Source

simplify TryGetPaddedRowSpan()

pull/1901/head
Anton Firszov 4 years ago
parent
commit
8d651ebc71
  1. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  2. 8
      src/ImageSharp/Memory/Buffer2D{T}.cs
  3. 25
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
  4. 18
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs
  5. 11
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs
  6. 2
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -179,7 +179,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
// PackFromRgbPlanes expects the destination to be padded, so try to get padded span containing extra elements from the next row.
// If we can't get such a padded row because we are on a MemoryGroup boundary or at the last row,
// pack pixels to a temporary, padded proxy buffer, then copy the relevant values to the destination row.
if (this.pixelBuffer.TryGetPaddedRowSpan(yy, 3, out Span<TPixel> destRow))
if (this.pixelBuffer.DangerousTryGetPaddedRowSpan(yy, 3, out Span<TPixel> destRow))
{
PixelOperations<TPixel>.Instance.PackFromRgbPlanes(this.configuration, r, g, b, destRow);
}

8
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -105,22 +105,22 @@ namespace SixLabors.ImageSharp.Memory
return this.FastMemoryGroup.GetRowSpanCoreUnsafe(y, this.Width);
}
internal bool TryGetPaddedRowSpan(int y, int padding, out Span<T> paddedSpan)
internal bool DangerousTryGetPaddedRowSpan(int y, int padding, out Span<T> paddedSpan)
{
DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
int stride = this.Width + padding;
Memory<T> memory = this.FastMemoryGroup.GetRemainingSliceOfBuffer(y * (long)this.Width);
Span<T> slice = this.FastMemoryGroup.GetRemainingSliceOfBuffer(y * (long)this.Width);
if (memory.Length < stride)
if (slice.Length < stride)
{
paddedSpan = default;
return false;
}
paddedSpan = memory.Span.Slice(0, stride);
paddedSpan = slice.Slice(0, stride);
return true;
}

25
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs

@ -57,31 +57,6 @@ namespace SixLabors.ImageSharp.Memory
return memory.Slice(bufferStart, length);
}
/// <summary>
/// Returns the slice of the buffer starting at global index <paramref name="start"/> that goes until the end of the buffer.
/// </summary>
internal static Memory<T> GetRemainingSliceOfBuffer<T>(this IMemoryGroup<T> group, long start)
where T : struct
{
Guard.NotNull(group, nameof(group));
Guard.IsTrue(group.IsValid, nameof(group), "Group must be valid!");
Guard.MustBeLessThan(start, group.TotalLength, nameof(start));
int bufferIdx = (int)(start / group.BufferLength);
// if (bufferIdx < 0 || bufferIdx >= group.Count)
if ((uint)bufferIdx >= group.Count)
{
throw new ArgumentOutOfRangeException(nameof(start));
}
int bufferStart = (int)(start % group.BufferLength);
Memory<T> memory = group[bufferIdx];
return memory.Slice(bufferStart);
}
internal static void CopyTo<T>(this IMemoryGroup<T> source, Span<T> target)
where T : struct
{

18
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs

@ -1,11 +1,16 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory.Internals;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Cached pointer or array data enabling fast <see cref="Span{T}"/> from
/// known <see cref="IMemoryOwner{T}"/> implementations.
/// </summary>
internal unsafe struct MemoryGroupSpanCache
{
public SpanCacheMode Mode;
@ -31,16 +36,13 @@ namespace SixLabors.ImageSharp.Memory
memoryGroupSpanCache.SinglePointer = unmanagedBuffer.Pointer;
}
}
else
else if (owner0 is UnmanagedBuffer<T>)
{
if (owner0 is UnmanagedBuffer<T>)
memoryGroupSpanCache.Mode = SpanCacheMode.MultiPointer;
memoryGroupSpanCache.MultiPointer = new void*[memoryOwners.Length];
for (int i = 0; i < memoryOwners.Length; i++)
{
memoryGroupSpanCache.Mode = SpanCacheMode.MultiPointer;
memoryGroupSpanCache.MultiPointer = new void*[memoryOwners.Length];
for (int i = 0; i < memoryOwners.Length; i++)
{
memoryGroupSpanCache.MultiPointer[i] = ((UnmanagedBuffer<T>)memoryOwners[i]).Pointer;
}
memoryGroupSpanCache.MultiPointer[i] = ((UnmanagedBuffer<T>)memoryOwners[i]).Pointer;
}
}

11
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

@ -279,6 +279,17 @@ namespace SixLabors.ImageSharp.Memory
}
}
/// <summary>
/// Returns the slice of the buffer starting at global index <paramref name="start"/> that goes until the end of the buffer.
/// </summary>
public Span<T> GetRemainingSliceOfBuffer(long start)
{
int bufferIdx = (int)(start / this.BufferLength);
int bufferStart = (int)(start % this.BufferLength);
Memory<T> memory = this[bufferIdx];
return memory.Span.Slice(bufferStart);
}
public static bool CanSwapContent(MemoryGroup<T> target, MemoryGroup<T> source) =>
source is Owned { Swappable: true } && target is Owned { Swappable: true };

2
tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
using Buffer2D<byte> buffer = this.MemoryAllocator.Allocate2D<byte>(3, 5);
bool expectSuccess = expectedBufferIndex >= 0;
bool success = buffer.TryGetPaddedRowSpan(y, padding, out Span<byte> paddedSpan);
bool success = buffer.DangerousTryGetPaddedRowSpan(y, padding, out Span<byte> paddedSpan);
Xunit.Assert.Equal(expectSuccess, success);
if (success)
{

Loading…
Cancel
Save