Browse Source

TryGetSinglePixelSpan -> DangerousTryGetSinglePixelMemory

af/UniformUnmanagedMemoryPoolMemoryAllocator-02-MemoryGuards
Anton Firszov 5 years ago
parent
commit
e1f15bc626
  1. 19
      src/ImageSharp/ImageFrame{TPixel}.cs
  2. 26
      src/ImageSharp/Image{TPixel}.cs
  3. 2
      tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
  4. 4
      tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
  5. 4
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  6. 10
      tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs
  7. 10
      tests/ImageSharp.Tests/Formats/Tiff/TiffTestUtils.cs
  8. 24
      tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs
  9. 10
      tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs
  10. 25
      tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
  11. 14
      tests/ImageSharp.Tests/Image/ImageTests.cs
  12. 10
      tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
  13. 4
      tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
  14. 4
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
  15. 19
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  16. 4
      tests/ImageSharp.Tests/TestUtilities/TestUtils.cs

19
src/ImageSharp/ImageFrame{TPixel}.cs

@ -285,28 +285,27 @@ namespace SixLabors.ImageSharp
} }
/// <summary> /// <summary>
/// Gets the representation of the pixels as a <see cref="Span{T}"/> in the source image's pixel format /// Gets the representation of the pixels as a <see cref="Memory{T}"/> in the source image's pixel format
/// stored in row major order, if the backing buffer is contiguous. /// stored in row major order, if the backing buffer is contiguous.
/// <para /> /// <para />
/// To ensure the memory is contiguous, <see cref="Configuration.MemoryAllocator"/> should be initialized /// To ensure the memory is contiguous, <see cref="Configuration.PreferContiguousImageBuffers"/> should be set
/// with a <see cref="MemoryAllocator"/> that enforces larger contiguous buffers. /// to true, preferably on a non-global configuration instance (not <see cref="Configuration.Default"/>).
/// See <see cref="MemoryAllocatorSettings.MinimumContiguousBlockSizeBytes"/>.
/// <para /> /// <para />
/// WARNING: Disposing or leaking the underlying image while still working with it's <see cref="Span{T}"/> /// WARNING: Disposing or leaking the underlying image while still working with the <paramref name="memory"/>'s <see cref="Span{T}"/>
/// might lead to memory corruption. /// might lead to memory corruption.
/// </summary> /// </summary>
/// <param name="span">The <see cref="Span{T}"/>.</param> /// <param name="memory">The <see cref="Memory{T}"/> referencing the image buffer.</param>
/// <returns>The <see cref="bool"/>.</returns> /// <returns>The <see cref="bool"/> indicating the success.</returns>
public bool TryGetSinglePixelSpan(out Span<TPixel> span) public bool DangerousTryGetSinglePixelMemory(out Memory<TPixel> memory)
{ {
IMemoryGroup<TPixel> mg = this.GetPixelMemoryGroup(); IMemoryGroup<TPixel> mg = this.GetPixelMemoryGroup();
if (mg.Count > 1) if (mg.Count > 1)
{ {
span = default; memory = default;
return false; return false;
} }
span = mg.Single().Span; memory = mg.Single();
return true; return true;
} }

26
src/ImageSharp/Image{TPixel}.cs

@ -321,26 +321,30 @@ namespace SixLabors.ImageSharp
} }
/// <summary> /// <summary>
/// Gets the representation of the pixels as a <see cref="Span{T}"/> in the source image's pixel format /// Gets the representation of the pixels as a <see cref="Memory{T}"/> in the source image's pixel format
/// stored in row major order, if the backing buffer is contiguous. /// stored in row major order, if the backing buffer is contiguous.
/// <para />
/// To ensure the memory is contiguous, <see cref="Configuration.PreferContiguousImageBuffers"/> should be set
/// to true, preferably on a non-global configuration instance (not <see cref="Configuration.Default"/>).
/// <para />
/// WARNING: Disposing or leaking the underlying image while still working with the <paramref name="memory"/>'s <see cref="Span{T}"/>
/// might lead to memory corruption.
/// </summary> /// </summary>
/// <param name="span">The <see cref="Span{T}"/>.</param> /// <param name="memory">The <see cref="Memory{T}"/> referencing the image buffer.</param>
/// <returns>The <see cref="bool"/>.</returns> /// <returns>The <see cref="bool"/> indicating the success.</returns>
public bool TryGetSinglePixelSpan(out Span<TPixel> span) public bool DangerousTryGetSinglePixelMemory(out Memory<TPixel> memory)
{ {
IMemoryGroup<TPixel> mg = this.GetPixelMemoryGroup(); IMemoryGroup<TPixel> mg = this.GetPixelMemoryGroup();
if (mg.Count == 1) if (mg.Count > 1)
{ {
span = mg[0].Span; memory = default;
return true; return false;
} }
span = default; memory = mg.Single();
return false; return true;
} }
public bool DangerousTryGetSinglePixelMemory(out Memory<TPixel> memory) => throw new NotImplementedException();
/// <summary> /// <summary>
/// Clones the current image /// Clones the current image
/// </summary> /// </summary>

2
tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs

@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
using Image<TPixel> image0 = provider.GetImage(); using Image<TPixel> image0 = provider.GetImage();
var targetBuffer = new TPixel[image0.Width * image0.Height]; var targetBuffer = new TPixel[image0.Width * image0.Height];
Assert.True(image0.TryGetSinglePixelSpan(out Span<TPixel> sourceBuffer)); Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory<TPixel> sourceBuffer));
sourceBuffer.CopyTo(targetBuffer); sourceBuffer.CopyTo(targetBuffer);

4
tests/ImageSharp.Tests/Drawing/DrawImageTests.cs

@ -128,8 +128,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (Image<Rgba32> background = provider.GetImage()) using (Image<Rgba32> background = provider.GetImage())
using (var overlay = new Image<Rgba32>(50, 50)) using (var overlay = new Image<Rgba32>(50, 50))
{ {
Assert.True(overlay.TryGetSinglePixelSpan(out Span<Rgba32> overlaySpan)); Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> overlayMem));
overlaySpan.Fill(Color.Black); overlayMem.Span.Fill(Color.Black);
background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F));

4
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -165,9 +165,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
ImageFrame<Rgba32> first = kumin1.Frames[i]; ImageFrame<Rgba32> first = kumin1.Frames[i];
ImageFrame<Rgba32> second = kumin2.Frames[i]; ImageFrame<Rgba32> second = kumin2.Frames[i];
Assert.True(second.TryGetSinglePixelSpan(out Span<Rgba32> secondSpan)); Assert.True(second.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> secondMemory));
first.ComparePixelBufferTo(secondSpan); first.ComparePixelBufferTo(secondMemory.Span);
} }
} }
} }

10
tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
} }
var testFile = TestFile.Create(path); var testFile = TestFile.Create(path);
Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(Configuration.Default, new FileInfo(testFile.FullPath)); Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(new FileInfo(testFile.FullPath));
if (useExactComparer) if (useExactComparer)
{ {
ImageComparer.Exact.VerifySimilarity(magickImage, image); ImageComparer.Exact.VerifySimilarity(magickImage, image);
@ -37,15 +37,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
} }
} }
public static Image<TPixel> DecodeWithMagick<TPixel>(Configuration configuration, FileInfo fileInfo) public static Image<TPixel> DecodeWithMagick<TPixel>(FileInfo fileInfo)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel> where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{ {
Configuration configuration = Configuration.Default.Clone();
configuration.PreferContiguousImageBuffers = true;
using (var magickImage = new MagickImage(fileInfo)) using (var magickImage = new MagickImage(fileInfo))
{ {
magickImage.AutoOrient(); magickImage.AutoOrient();
var result = new Image<TPixel>(configuration, magickImage.Width, magickImage.Height); var result = new Image<TPixel>(configuration, magickImage.Width, magickImage.Height);
Assert.True(result.TryGetSinglePixelSpan(out Span<TPixel> resultPixels)); Assert.True(result.DangerousTryGetSinglePixelMemory(out Memory<TPixel> resultPixels));
using (IUnsafePixelCollection<ushort> pixels = magickImage.GetPixelsUnsafe()) using (IUnsafePixelCollection<ushort> pixels = magickImage.GetPixelsUnsafe())
{ {
@ -54,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
PixelOperations<TPixel>.Instance.FromRgba32Bytes( PixelOperations<TPixel>.Instance.FromRgba32Bytes(
configuration, configuration,
data, data,
resultPixels, resultPixels.Span,
resultPixels.Length); resultPixels.Length);
} }

10
tests/ImageSharp.Tests/Formats/Tiff/TiffTestUtils.cs

@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel> where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{ {
var testFile = TestFile.Create(encodedImagePath); var testFile = TestFile.Create(encodedImagePath);
Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(Configuration.Default, new FileInfo(testFile.FullPath)); Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(new FileInfo(testFile.FullPath));
if (useExactComparer) if (useExactComparer)
{ {
ImageComparer.Exact.VerifySimilarity(magickImage, image); ImageComparer.Exact.VerifySimilarity(magickImage, image);
@ -34,14 +34,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
} }
} }
public static Image<TPixel> DecodeWithMagick<TPixel>(Configuration configuration, FileInfo fileInfo) public static Image<TPixel> DecodeWithMagick<TPixel>(FileInfo fileInfo)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel> where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{ {
Configuration configuration = Configuration.Default.Clone();
configuration.PreferContiguousImageBuffers = true;
using var magickImage = new MagickImage(fileInfo); using var magickImage = new MagickImage(fileInfo);
magickImage.AutoOrient(); magickImage.AutoOrient();
var result = new Image<TPixel>(configuration, magickImage.Width, magickImage.Height); var result = new Image<TPixel>(configuration, magickImage.Width, magickImage.Height);
Assert.True(result.TryGetSinglePixelSpan(out Span<TPixel> resultPixels)); Assert.True(result.DangerousTryGetSinglePixelMemory(out Memory<TPixel> resultPixels));
using IUnsafePixelCollection<ushort> pixels = magickImage.GetPixelsUnsafe(); using IUnsafePixelCollection<ushort> pixels = magickImage.GetPixelsUnsafe();
byte[] data = pixels.ToByteArray(PixelMapping.RGBA); byte[] data = pixels.ToByteArray(PixelMapping.RGBA);
@ -49,7 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
PixelOperations<TPixel>.Instance.FromRgba32Bytes( PixelOperations<TPixel>.Instance.FromRgba32Bytes(
configuration, configuration,
data, data,
resultPixels, resultPixels.Span,
resultPixels.Length); resultPixels.Length);
return result; return result;

24
tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs

@ -211,9 +211,9 @@ namespace SixLabors.ImageSharp.Tests
using (Image<TPixel> cloned = img.Frames.CloneFrame(0)) using (Image<TPixel> cloned = img.Frames.CloneFrame(0))
{ {
Assert.Equal(2, img.Frames.Count); Assert.Equal(2, img.Frames.Count);
Assert.True(img.TryGetSinglePixelSpan(out Span<TPixel> imgSpan)); Assert.True(img.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imgMem));
cloned.ComparePixelBufferTo(imgSpan); cloned.ComparePixelBufferTo(imgMem);
} }
} }
} }
@ -225,15 +225,15 @@ namespace SixLabors.ImageSharp.Tests
{ {
using (Image<TPixel> img = provider.GetImage()) using (Image<TPixel> img = provider.GetImage())
{ {
Assert.True(img.TryGetSinglePixelSpan(out Span<TPixel> imgSpan)); Assert.True(img.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imgMemory));
TPixel[] sourcePixelData = imgSpan.ToArray(); TPixel[] sourcePixelData = imgMemory.ToArray();
using var imageFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10); using var imageFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10);
using ImageFrame addedFrame = img.Frames.AddFrame(imageFrame); using ImageFrame addedFrame = img.Frames.AddFrame(imageFrame);
using (Image<TPixel> cloned = img.Frames.ExportFrame(0)) using (Image<TPixel> cloned = img.Frames.ExportFrame(0))
{ {
Assert.Equal(1, img.Frames.Count); Assert.Equal(1, img.Frames.Count);
cloned.ComparePixelBufferTo(sourcePixelData); cloned.ComparePixelBufferTo(sourcePixelData.AsSpan());
} }
} }
} }
@ -261,8 +261,8 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void AddFrameFromPixelData() public void AddFrameFromPixelData()
{ {
Assert.True(this.Image.Frames.RootFrame.TryGetSinglePixelSpan(out Span<Rgba32> imgSpan)); Assert.True(this.Image.Frames.RootFrame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imgMem));
Rgba32[] pixelData = imgSpan.ToArray(); Rgba32[] pixelData = imgMem.ToArray();
using ImageFrame<Rgba32> addedFrame = this.Image.Frames.AddFrame(pixelData); using ImageFrame<Rgba32> addedFrame = this.Image.Frames.AddFrame(pixelData);
Assert.Equal(2, this.Image.Frames.Count); Assert.Equal(2, this.Image.Frames.Count);
} }
@ -273,8 +273,8 @@ namespace SixLabors.ImageSharp.Tests
using var otherFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10); using var otherFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10);
using ImageFrame<Rgba32> addedFrame = this.Image.Frames.AddFrame(otherFrame); using ImageFrame<Rgba32> addedFrame = this.Image.Frames.AddFrame(otherFrame);
Assert.True(otherFrame.TryGetSinglePixelSpan(out Span<Rgba32> otherFrameSpan)); Assert.True(otherFrame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> otherFrameMem));
addedFrame.ComparePixelBufferTo(otherFrameSpan); addedFrame.ComparePixelBufferTo(otherFrameMem.Span);
Assert.NotEqual(otherFrame, addedFrame); Assert.NotEqual(otherFrame, addedFrame);
} }
@ -284,8 +284,8 @@ namespace SixLabors.ImageSharp.Tests
using var otherFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10); using var otherFrame = new ImageFrame<Rgba32>(Configuration.Default, 10, 10);
using ImageFrame<Rgba32> addedFrame = this.Image.Frames.InsertFrame(0, otherFrame); using ImageFrame<Rgba32> addedFrame = this.Image.Frames.InsertFrame(0, otherFrame);
Assert.True(otherFrame.TryGetSinglePixelSpan(out Span<Rgba32> otherFrameSpan)); Assert.True(otherFrame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> otherFrameMem));
addedFrame.ComparePixelBufferTo(otherFrameSpan); addedFrame.ComparePixelBufferTo(otherFrameMem.Span);
Assert.NotEqual(otherFrame, addedFrame); Assert.NotEqual(otherFrame, addedFrame);
} }
@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.Tests
IEnumerable<ImageFrame<Rgba32>> frames = image.Frames; IEnumerable<ImageFrame<Rgba32>> frames = image.Frames;
foreach (ImageFrame<Rgba32> frame in frames) foreach (ImageFrame<Rgba32> frame in frames)
{ {
Assert.True(frame.TryGetSinglePixelSpan(out Span<Rgba32> span)); Assert.True(frame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> _));
} }
} }

10
tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs

@ -158,8 +158,8 @@ namespace SixLabors.ImageSharp.Tests
var expectedClone = (Image<TPixel>)cloned; var expectedClone = (Image<TPixel>)cloned;
Assert.True(img.TryGetSinglePixelSpan(out Span<TPixel> imgSpan)); Assert.True(img.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imgMem));
expectedClone.ComparePixelBufferTo(imgSpan); expectedClone.ComparePixelBufferTo(imgMem);
} }
} }
} }
@ -171,8 +171,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
using (Image<TPixel> img = provider.GetImage()) using (Image<TPixel> img = provider.GetImage())
{ {
Assert.True(img.TryGetSinglePixelSpan(out Span<TPixel> imgSpan)); Assert.True(img.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imgMem));
var sourcePixelData = imgSpan.ToArray(); TPixel[] sourcePixelData = imgMem.ToArray();
ImageFrameCollection nonGenericFrameCollection = img.Frames; ImageFrameCollection nonGenericFrameCollection = img.Frames;
@ -182,7 +182,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(1, img.Frames.Count); Assert.Equal(1, img.Frames.Count);
var expectedClone = (Image<TPixel>)cloned; var expectedClone = (Image<TPixel>)cloned;
expectedClone.ComparePixelBufferTo(sourcePixelData); expectedClone.ComparePixelBufferTo(sourcePixelData.AsSpan());
} }
} }
} }

25
tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

@ -9,8 +9,10 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit; using Xunit;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
@ -132,8 +134,8 @@ namespace SixLabors.ImageSharp.Tests
using (var image = Image.WrapMemory(cfg, memory, 5, 5, metaData)) using (var image = Image.WrapMemory(cfg, memory, 5, 5, metaData))
{ {
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
ref Rgba32 pixel0 = ref imageSpan[0]; ref Rgba32 pixel0 = ref imageMem.Span[0];
Assert.True(Unsafe.AreSame(ref array[0], ref pixel0)); Assert.True(Unsafe.AreSame(ref array[0], ref pixel0));
Assert.Equal(cfg, image.GetConfiguration()); Assert.Equal(cfg, image.GetConfiguration());
@ -160,8 +162,7 @@ namespace SixLabors.ImageSharp.Tests
using (var image = Image.WrapMemory(memory, bmp.Width, bmp.Height)) using (var image = Image.WrapMemory(memory, bmp.Width, bmp.Height))
{ {
Assert.Equal(memory, image.GetRootFramePixelBuffer().DangerousGetSingleMemory()); Assert.Equal(memory, image.GetRootFramePixelBuffer().DangerousGetSingleMemory());
Assert.True(image.TryGetSinglePixelSpan(out Span<Bgra32> imageSpan)); image.GetPixelMemoryGroup().Fill(bg);
imageSpan.Fill(bg);
for (var i = 10; i < 20; i++) for (var i = 10; i < 20; i++)
{ {
image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg);
@ -196,8 +197,7 @@ namespace SixLabors.ImageSharp.Tests
using (var image = Image.WrapMemory(memoryManager, bmp.Width, bmp.Height)) using (var image = Image.WrapMemory(memoryManager, bmp.Width, bmp.Height))
{ {
Assert.Equal(memoryManager.Memory, image.GetRootFramePixelBuffer().DangerousGetSingleMemory()); Assert.Equal(memoryManager.Memory, image.GetRootFramePixelBuffer().DangerousGetSingleMemory());
Assert.True(image.TryGetSinglePixelSpan(out Span<Bgra32> imageSpan)); image.GetPixelMemoryGroup().Fill(bg);
imageSpan.Fill(bg);
for (var i = 10; i < 20; i++) for (var i = 10; i < 20; i++)
{ {
image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg);
@ -225,8 +225,8 @@ namespace SixLabors.ImageSharp.Tests
using (var image = Image.WrapMemory<Rgba32>(cfg, memory, 5, 5, metaData)) using (var image = Image.WrapMemory<Rgba32>(cfg, memory, 5, 5, metaData))
{ {
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
ref Rgba32 pixel0 = ref imageSpan[0]; ref Rgba32 pixel0 = ref imageMem.Span[0];
Assert.True(Unsafe.AreSame(ref Unsafe.As<byte, Rgba32>(ref array[0]), ref pixel0)); Assert.True(Unsafe.AreSame(ref Unsafe.As<byte, Rgba32>(ref array[0]), ref pixel0));
Assert.Equal(cfg, image.GetConfiguration()); Assert.Equal(cfg, image.GetConfiguration());
@ -262,8 +262,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(pixelSpan.Length, imageSpan.Length); Assert.Equal(pixelSpan.Length, imageSpan.Length);
Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference())); Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference()));
Assert.True(image.TryGetSinglePixelSpan(out imageSpan)); image.GetPixelMemoryGroup().Fill(bg);
imageSpan.Fill(bg);
for (var i = 10; i < 20; i++) for (var i = 10; i < 20; i++)
{ {
image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg);
@ -293,7 +292,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
using (var image = Image.WrapMemory<Rgba32>(cfg, ptr, 5, 5, metaData)) using (var image = Image.WrapMemory<Rgba32>(cfg, ptr, 5, 5, metaData))
{ {
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
Span<Rgba32> imageSpan = imageMem.Span;
ref Rgba32 pixel0 = ref imageSpan[0]; ref Rgba32 pixel0 = ref imageSpan[0];
Assert.True(Unsafe.AreSame(ref array[0], ref pixel0)); Assert.True(Unsafe.AreSame(ref array[0], ref pixel0));
ref Rgba32 pixel_1 = ref imageSpan[imageSpan.Length - 1]; ref Rgba32 pixel_1 = ref imageSpan[imageSpan.Length - 1];
@ -331,8 +331,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(pixelSpan.Length, imageSpan.Length); Assert.Equal(pixelSpan.Length, imageSpan.Length);
Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference())); Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference()));
Assert.True(image.TryGetSinglePixelSpan(out imageSpan)); image.GetPixelMemoryGroup().Fill(bg);
imageSpan.Fill(bg);
for (var i = 10; i < 20; i++) for (var i = 10; i < 20; i++)
{ {
image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg);

14
tests/ImageSharp.Tests/Image/ImageTests.cs

@ -29,8 +29,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
Assert.Equal(11, image.Width); Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height); Assert.Equal(23, image.Height);
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
Assert.Equal(11 * 23, imageSpan.Length); Assert.Equal(11 * 23, imageMem.Length);
image.ComparePixelBufferTo(default(Rgba32)); image.ComparePixelBufferTo(default(Rgba32));
Assert.Equal(Configuration.Default, image.GetConfiguration()); Assert.Equal(Configuration.Default, image.GetConfiguration());
@ -46,8 +46,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
Assert.Equal(11, image.Width); Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height); Assert.Equal(23, image.Height);
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
Assert.Equal(11 * 23, imageSpan.Length); Assert.Equal(11 * 23, imageMem.Length);
image.ComparePixelBufferTo(default(Rgba32)); image.ComparePixelBufferTo(default(Rgba32));
Assert.Equal(configuration, image.GetConfiguration()); Assert.Equal(configuration, image.GetConfiguration());
@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
Assert.Equal(11, image.Width); Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height); Assert.Equal(23, image.Height);
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
Assert.Equal(11 * 23, imageSpan.Length); Assert.Equal(11 * 23, imageMem.Length);
image.ComparePixelBufferTo(color); image.ComparePixelBufferTo(color);
Assert.Equal(configuration, image.GetConfiguration()); Assert.Equal(configuration, image.GetConfiguration());
@ -272,7 +272,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Throws<ObjectDisposedException>(() => { var res = image.Clone(this.configuration); }); Assert.Throws<ObjectDisposedException>(() => { var res = image.Clone(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { var res = image.CloneAs<Rgba32>(this.configuration); }); Assert.Throws<ObjectDisposedException>(() => { var res = image.CloneAs<Rgba32>(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { var res = image.GetPixelRowSpan(default); }); Assert.Throws<ObjectDisposedException>(() => { var res = image.GetPixelRowSpan(default); });
Assert.Throws<ObjectDisposedException>(() => { var res = image.TryGetSinglePixelSpan(out var _); }); Assert.Throws<ObjectDisposedException>(() => { var res = image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> _); });
// Image // Image
Assert.Throws<ObjectDisposedException>(() => { var res = genericImage.CloneAs<Rgba32>(this.configuration); }); Assert.Throws<ObjectDisposedException>(() => { var res = genericImage.CloneAs<Rgba32>(this.configuration); });

10
tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs

@ -33,19 +33,19 @@ namespace SixLabors.ImageSharp.Tests
configuration.PreferContiguousImageBuffers = true; configuration.PreferContiguousImageBuffers = true;
using var image = new Image<Rgba32>(configuration, 8192, 4096); using var image = new Image<Rgba32>(configuration, 8192, 4096);
Assert.True(image.TryGetSinglePixelSpan(out Span<Rgba32> span)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> mem));
Assert.Equal(8192 * 4096, span.Length); Assert.Equal(8192 * 4096, mem.Length);
} }
} }
[Theory] [Theory]
[WithBasicTestPatternImages(width: 10, height: 10, PixelTypes.Rgba32)] [WithBasicTestPatternImages(width: 10, height: 10, PixelTypes.Rgba32)]
public void TryGetSinglePixelSpan_WhenImageTooLarge_ReturnsFalse(TestImageProvider<Rgba32> provider) public void DangerousTryGetSinglePixelMemory_WhenImageTooLarge_ReturnsFalse(TestImageProvider<Rgba32> provider)
{ {
provider.LimitAllocatorBufferCapacity().InPixels(10); provider.LimitAllocatorBufferCapacity().InPixels(10);
using Image<Rgba32> image = provider.GetImage(); using Image<Rgba32> image = provider.GetImage();
Assert.False(image.TryGetSinglePixelSpan(out Span<Rgba32> imageSpan)); Assert.False(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> mem));
Assert.False(image.Frames.RootFrame.TryGetSinglePixelSpan(out Span<Rgba32> imageFrameSpan)); Assert.False(image.Frames.RootFrame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> _));
} }
} }
} }

4
tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs

@ -239,9 +239,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
private static void VerifyAllPixelsAreWhiteOrTransparent<TPixel>(Image<TPixel> image) private static void VerifyAllPixelsAreWhiteOrTransparent<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.True(image.Frames.RootFrame.TryGetSinglePixelSpan(out Span<TPixel> data)); Assert.True(image.Frames.RootFrame.DangerousTryGetSinglePixelMemory(out Memory<TPixel> data));
var white = new Rgb24(255, 255, 255); var white = new Rgb24(255, 255, 255);
foreach (TPixel pixel in data) foreach (TPixel pixel in data.Span)
{ {
Rgba32 rgba = default; Rgba32 rgba = default;
pixel.ToRgba32(ref rgba); pixel.ToRgba32(ref rgba);

4
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs

@ -269,8 +269,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{ {
using (Image<TPixel> image0 = provider.GetImage()) using (Image<TPixel> image0 = provider.GetImage())
{ {
Assert.True(image0.TryGetSinglePixelSpan(out Span<TPixel> imageSpan)); Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imageMem));
var mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageSpan); var mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageMem.Span);
using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height)) using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height))
{ {

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

@ -396,12 +396,18 @@ namespace SixLabors.ImageSharp.Tests
Span<TPixel> expectedPixels) Span<TPixel> expectedPixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.True(image.TryGetSinglePixelSpan(out Span<TPixel> actualPixels)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<TPixel> actualPixels));
CompareBuffers(expectedPixels, actualPixels); CompareBuffers(expectedPixels, actualPixels.Span);
return image; return image;
} }
public static Image<TPixel> ComparePixelBufferTo<TPixel>(
this Image<TPixel> image,
Memory<TPixel> expectedPixels)
where TPixel : unmanaged, IPixel<TPixel> =>
ComparePixelBufferTo(image, expectedPixels.Span);
public static void CompareBuffers<T>(Span<T> expected, Span<T> actual) public static void CompareBuffers<T>(Span<T> expected, Span<T> actual)
where T : struct, IEquatable<T> where T : struct, IEquatable<T>
{ {
@ -477,7 +483,8 @@ namespace SixLabors.ImageSharp.Tests
public static ImageFrame<TPixel> ComparePixelBufferTo<TPixel>(this ImageFrame<TPixel> imageFrame, TPixel expectedPixel) public static ImageFrame<TPixel> ComparePixelBufferTo<TPixel>(this ImageFrame<TPixel> imageFrame, TPixel expectedPixel)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.True(imageFrame.TryGetSinglePixelSpan(out Span<TPixel> actualPixels)); Assert.True(imageFrame.DangerousTryGetSinglePixelMemory(out Memory<TPixel> actualPixelMem));
Span<TPixel> actualPixels = actualPixelMem.Span;
for (int i = 0; i < actualPixels.Length; i++) for (int i = 0; i < actualPixels.Length; i++)
{ {
@ -492,7 +499,8 @@ namespace SixLabors.ImageSharp.Tests
Span<TPixel> expectedPixels) Span<TPixel> expectedPixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.True(image.TryGetSinglePixelSpan(out Span<TPixel> actual)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<TPixel> actualMem));
Span<TPixel> actual = actualMem.Span;
Assert.True(expectedPixels.Length == actual.Length, "Buffer sizes are not equal!"); Assert.True(expectedPixels.Length == actual.Length, "Buffer sizes are not equal!");
for (int i = 0; i < expectedPixels.Length; i++) for (int i = 0; i < expectedPixels.Length; i++)
@ -696,7 +704,8 @@ namespace SixLabors.ImageSharp.Tests
{ {
var image = new Image<Rgba32>(buffer.Width, buffer.Height); var image = new Image<Rgba32>(buffer.Width, buffer.Height);
Assert.True(image.Frames.RootFrame.TryGetSinglePixelSpan(out Span<Rgba32> pixels)); Assert.True(image.Frames.RootFrame.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> pixelMem));
Span<Rgba32> pixels = pixelMem.Span;
Span<float> bufferSpan = buffer.DangerousGetSingleSpan(); Span<float> bufferSpan = buffer.DangerousGetSingleSpan();
for (int i = 0; i < bufferSpan.Length; i++) for (int i = 0; i < bufferSpan.Length; i++)

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

@ -280,8 +280,8 @@ namespace SixLabors.ImageSharp.Tests
using (Image<TPixel> image0 = provider.GetImage()) using (Image<TPixel> image0 = provider.GetImage())
{ {
Assert.True(image0.TryGetSinglePixelSpan(out Span<TPixel> imageSpan)); Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imageMem));
var mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageSpan); var mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageMem.Span);
using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height)) using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height))
{ {

Loading…
Cancel
Save