Skip to content

Commit d19dcee

Browse files
committed
contiguous memory checking
1 parent f1f43df commit d19dcee

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

Diff for: SFI.Formats/Images/SharpImage.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,19 @@ public override Services.IImage Resize(int newWith, int newHeight, bool use32bpp
132132
public class SharpImageData<TPixel> : MemoryImageData<IImage> where TPixel : unmanaged, IPixel<TPixel>
133133
{
134134
readonly Image<TPixel> data;
135-
readonly bool preferSlicing;
135+
136+
public override bool IsContiguous { get; }
136137

137138
public SharpImageData(SharpImage image, Image<TPixel> data) : base(image, data.Width * Unsafe.SizeOf<TPixel>(), data.PixelType.BitsPerPixel)
138139
{
139140
this.data = data;
140141
// On contiguous buffers, the base implementation of GetPixel and GetRow is better since there is no MemoryManager allocation
141-
preferSlicing = data.DangerousTryGetSinglePixelMemory(out _);
142+
IsContiguous = data.DangerousTryGetSinglePixelMemory(out _);
142143
}
143144

144145
public override Memory<byte> GetPixel(int x, int y)
145146
{
146-
if(preferSlicing)
147+
if(IsContiguous)
147148
{
148149
return base.GetPixel(x, y);
149150
}
@@ -153,7 +154,7 @@ public override Memory<byte> GetPixel(int x, int y)
153154

154155
public override Memory<byte> GetRow(int y)
155156
{
156-
if(preferSlicing)
157+
if(IsContiguous)
157158
{
158159
return base.GetRow(y);
159160
}

Diff for: SFI/Services/IImage.cs

+23
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ public interface IImage<TUnderlying> : IImage
130130
/// </summary>
131131
public interface IImageData : IMemoryOwner<byte>, IStreamFactory
132132
{
133+
/// <summary>
134+
/// Whether the image data is backed by a contiguous range of memory, in which
135+
/// case the <see cref="IMemoryOwner{T}.Memory"/> member is usable and describable
136+
/// by <see cref="Scan0"/> and <see cref="Stride"/>.
137+
/// </summary>
138+
bool IsContiguous { get; }
139+
133140
/// <summary>
134141
/// The offset of the top-left pixel in the data.
135142
/// </summary>
@@ -348,6 +355,9 @@ public ImageData(ImageBase<TUnderlying> image)
348355

349356
StreamFactoryAccess IStreamFactory.Access => StreamFactoryAccess.Parallel;
350357

358+
/// <inheritdoc/>
359+
public abstract bool IsContiguous { get; }
360+
351361
/// <inheritdoc/>
352362
public abstract int Scan0 { get; }
353363

@@ -387,6 +397,9 @@ Stream IStreamFactory.Open()
387397

388398
public abstract class MemoryImageData<TUnderlying> : ImageData<TUnderlying> where TUnderlying : class
389399
{
400+
/// <inheritdoc/>
401+
public override bool IsContiguous => true;
402+
390403
/// <inheritdoc/>
391404
public override int Scan0 { get; }
392405

@@ -430,9 +443,18 @@ public MemoryImageData(ImageBase<TUnderlying> image, int stride, int bitDepth) :
430443
RowSize = (Width * bitDepth + 7) / 8;
431444
}
432445

446+
private void CheckContiguous()
447+
{
448+
if(!IsContiguous)
449+
{
450+
throw new NotImplementedException("This operation is not implemented for non-contiguous memory.");
451+
}
452+
}
453+
433454
/// <inheritdoc/>
434455
public override Memory<byte> GetPixel(int x, int y)
435456
{
457+
CheckContiguous();
436458
var pixelSize = Math.DivRem(BitDepth, 8, out var rem);
437459
if(rem == 0)
438460
{
@@ -444,6 +466,7 @@ public override Memory<byte> GetPixel(int x, int y)
444466
/// <inheritdoc/>
445467
public override Memory<byte> GetRow(int y)
446468
{
469+
CheckContiguous();
447470
return Memory.Slice(Scan0 + Stride * y, RowSize);
448471
}
449472

0 commit comments

Comments
 (0)