diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 3faa072dd3..1d7f33a9a5 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -24,7 +24,8 @@ namespace SixLabors.ImageSharp.Advanced
=> GetConfiguration((IConfigurable)source);
///
- /// Gets the storing the whole pixel buffer in row major order.
+ /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format
+ /// stored in row major order.
///
/// The Pixel format.
/// The source
@@ -36,7 +37,8 @@ namespace SixLabors.ImageSharp.Advanced
}
///
- /// Gets the storing the whole pixel buffer in row major order.
+ /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format
+ /// stored in row major order.
///
/// The Pixel format.
/// The source
@@ -48,70 +50,98 @@ namespace SixLabors.ImageSharp.Advanced
}
///
- /// Returns a reference to the 0th element of the Pixel buffer,
- /// allowing direct manipulation of pixel data through unsafe operations.
- /// The pixel buffer is a contiguous memory area containing Width*Height TPixel elements laid out in row-major order.
+ /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format
+ /// stored in row major order.
///
- /// The Pixel format.
- /// The source image frame
- /// A pinnable reference the first root of the pixel buffer.
- public static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(this ImageFrame source)
+ /// The type of the pixel.
+ /// The source.
+ /// The
+ public static Span GetPixelSpan(this ImageFrame source)
where TPixel : struct, IPixel
- => ref DangerousGetPinnableReferenceToPixelBuffer((IPixelSource)source);
+ => source.GetPixelMemory().Span;
///
- /// Returns a reference to the 0th element of the Pixel buffer,
- /// allowing direct manipulation of pixel data through unsafe operations.
- /// The pixel buffer is a contigous memory area containing Width*Height TPixel elements layed out in row-major order.
+ /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format
+ /// stored in row major order.
///
- /// The Pixel format.
- /// The source image
- /// A pinnable reference the first root of the pixel buffer.
- public static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(this Image source)
+ /// The type of the pixel.
+ /// The source.
+ /// The
+ public static Span GetPixelSpan(this Image source)
where TPixel : struct, IPixel
- => ref source.Frames.RootFrame.DangerousGetPinnableReferenceToPixelBuffer();
+ => source.Frames.RootFrame.GetPixelSpan();
///
- /// Gets the representation of the pixels as an area of contiguous memory in the given pixel format.
+ /// Gets the representation of the pixels as a of contiguous memory
+ /// at row beginning from the the first pixel on that row.
///
/// The type of the pixel.
/// The source.
+ /// The row.
/// The
- internal static Span GetPixelSpan(this ImageFrame source)
+ public static Memory GetPixelRowMemory(this ImageFrame source, int rowIndex)
where TPixel : struct, IPixel
- => GetSpan(source);
+ => source.PixelBuffer.GetRowMemory(rowIndex);
///
- /// Gets the representation of the pixels as an area of contiguous memory at row 'y' beginning from the the first pixel on that row.
+ /// Gets the representation of the pixels as of of contiguous memory
+ /// at row beginning from the the first pixel on that row.
///
/// The type of the pixel.
/// The source.
- /// The row.
+ /// The row.
/// The
- internal static Span GetPixelRowSpan(this ImageFrame source, int row)
+ public static Memory GetPixelRowMemory(this Image source, int rowIndex)
where TPixel : struct, IPixel
- => GetSpan(source, row);
+ => source.Frames.RootFrame.GetPixelRowMemory(rowIndex);
///
- /// Gets the representation of the pixels as an area of contiguous memory in the given pixel format.
+ /// Gets the representation of the pixels as a of contiguous memory
+ /// at row beginning from the the first pixel on that row.
///
/// The type of the pixel.
/// The source.
+ /// The row.
/// The
- internal static Span GetPixelSpan(this Image source)
+ public static Span GetPixelRowSpan(this ImageFrame source, int rowIndex)
where TPixel : struct, IPixel
- => source.Frames.RootFrame.GetPixelSpan();
+ => source.PixelBuffer.GetRowSpan(rowIndex);
///
- /// Gets the representation of the pixels as an area of contiguous memory at row 'y' beginning from the the first pixel on that row.
+ /// Gets the representation of the pixels as of of contiguous memory
+ /// at row beginning from the the first pixel on that row.
///
/// The type of the pixel.
/// The source.
- /// The row.
+ /// The row.
/// The
- internal static Span GetPixelRowSpan(this Image source, int row)
+ public static Span GetPixelRowSpan(this Image source, int rowIndex)
+ where TPixel : struct, IPixel
+ => source.Frames.RootFrame.GetPixelRowSpan(rowIndex);
+
+ ///
+ /// Returns a reference to the 0th element of the Pixel buffer,
+ /// allowing direct manipulation of pixel data through unsafe operations.
+ /// The pixel buffer is a contiguous memory area containing Width*Height TPixel elements laid out in row-major order.
+ ///
+ /// The Pixel format.
+ /// The source image frame
+ /// A pinnable reference the first root of the pixel buffer.
+ public static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(this ImageFrame source)
+ where TPixel : struct, IPixel
+ => ref DangerousGetPinnableReferenceToPixelBuffer((IPixelSource)source);
+
+ ///
+ /// Returns a reference to the 0th element of the Pixel buffer,
+ /// allowing direct manipulation of pixel data through unsafe operations.
+ /// The pixel buffer is a contigous memory area containing Width*Height TPixel elements layed out in row-major order.
+ ///
+ /// The Pixel format.
+ /// The source image
+ /// A pinnable reference the first root of the pixel buffer.
+ public static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(this Image source)
where TPixel : struct, IPixel
- => source.Frames.RootFrame.GetPixelRowSpan(row);
+ => ref source.Frames.RootFrame.DangerousGetPinnableReferenceToPixelBuffer();
///
/// Gets the assigned to 'source'.
diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs
index 6c07a20d31..c236f250c0 100644
--- a/src/ImageSharp/Memory/Buffer2DExtensions.cs
+++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs
@@ -50,6 +50,20 @@ namespace SixLabors.ImageSharp.Memory
return buffer.GetSpan().Slice(y * buffer.Width, buffer.Width);
}
+ ///
+ /// Gets a to the row 'y' beginning from the pixel at the first pixel on that row.
+ ///
+ /// The buffer
+ /// The y (row) coordinate
+ /// The element type
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Memory GetRowMemory(this IBuffer2D buffer, int y)
+ where T : struct
+ {
+ return buffer.Buffer.Memory.Slice(y * buffer.Width, buffer.Width);
+ }
+
///
/// Returns the size of the buffer.
///
diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
index c148667424..2825ddd770 100644
--- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
+++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
@@ -21,20 +21,77 @@ namespace SixLabors.ImageSharp.Tests.Advanced
public void WhenMemoryIsOwned(TestImageProvider provider)
where TPixel : struct, IPixel
{
- using (Image image = provider.GetImage())
+ using (Image image0 = provider.GetImage())
{
- Memory memory = image.GetPixelMemory();
- Assert.Equal(image.Width * image.Height, memory.Length);
+ var targetBuffer = new TPixel[image0.Width * image0.Height];
- var targetBuffer = new TPixel[image.Width * image.Height];
+ // Act:
+ Memory memory = image0.GetPixelMemory();
+
+ // Assert:
+ Assert.Equal(image0.Width * image0.Height, memory.Length);
memory.Span.CopyTo(targetBuffer);
- image.ComparePixelBufferTo(targetBuffer);
+ using (Image image1 = provider.GetImage())
+ {
+ // We are using a copy of the original image for assertion
+ image1.ComparePixelBufferTo(targetBuffer);
+ }
+ }
+ }
+ }
+
+ [Theory]
+ [WithSolidFilledImages(1, 1, "Red", PixelTypes.Rgba32)]
+ [WithTestPatternImages(131, 127, PixelTypes.Rgba32 | PixelTypes.Bgr24)]
+ public void GetPixelRowMemory(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = provider.GetImage())
+ {
+ var targetBuffer = new TPixel[image.Width * image.Height];
+
+ // Act:
+ for (int y = 0; y < image.Height; y++)
+ {
+ Memory rowMemory = image.GetPixelRowMemory(y);
+ rowMemory.Span.CopyTo(targetBuffer.AsSpan(image.Width * y));
+ }
+
+ // Assert:
+ using (Image image1 = provider.GetImage())
+ {
+ // We are using a copy of the original image for assertion
+ image1.ComparePixelBufferTo(targetBuffer);
}
}
}
-
+ [Theory]
+ [WithSolidFilledImages(1, 1, "Red", PixelTypes.Rgba32)]
+ [WithTestPatternImages(131, 127, PixelTypes.Rgba32 | PixelTypes.Bgr24)]
+ public void GetPixelRowSpan(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = provider.GetImage())
+ {
+ var targetBuffer = new TPixel[image.Width * image.Height];
+
+ // Act:
+ for (int y = 0; y < image.Height; y++)
+ {
+ Span rowMemory = image.GetPixelRowSpan(y);
+ rowMemory.CopyTo(targetBuffer.AsSpan(image.Width * y));
+ }
+
+ // Assert:
+ using (Image image1 = provider.GetImage())
+ {
+ // We are using a copy of the original image for assertion
+ image1.ComparePixelBufferTo(targetBuffer);
+ }
+ }
+ }
[Theory]
[WithTestPatternImages(131, 127, PixelTypes.Rgba32 | PixelTypes.Bgr24)]