From 80e0eee04fc9a672f3d2174fa1e2d2f65894d00a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 7 Feb 2020 03:54:37 +0100 Subject: [PATCH] change AdvancedImageExtensions public API-s --- .../Advanced/AdvancedImageExtensions.cs | 107 ++++++++---------- .../Advanced/AdvancedImageExtensionsTests.cs | 29 +---- .../Image/ImageTests.WrapMemory.cs | 5 +- 3 files changed, 56 insertions(+), 85 deletions(-) diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 79a863ff4..665d0e28b 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Linq; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; @@ -40,7 +41,7 @@ namespace SixLabors.ImageSharp.Advanced => GetConfiguration((IConfigurationProvider)source); /// - /// Gets the configuration . + /// Gets the configuration. /// /// The source image /// Returns the bounds of the image @@ -48,15 +49,56 @@ namespace SixLabors.ImageSharp.Advanced => source?.Configuration ?? Configuration.Default; /// - /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format - /// stored in row major order. + /// Gets the representation of the pixels as a containing the backing pixel data of the image + /// stored in row major order, as a list of contiguous blocks in the source image's pixel format. /// + /// The source image. /// The type of the pixel. - /// The source. + /// The . + /// + /// Certain Image Processors may invalidate the returned and all it's buffers, + /// therefore it's not recommended to mutate the image while holding a reference to it's . + /// + public static IMemoryGroup GetPixelMemoryGroup(this ImageFrame source) + where TPixel : struct, IPixel + => source.PixelBuffer.MemoryGroup.View; + + /// + /// Gets the representation of the pixels as a containing the backing pixel data of the image + /// stored in row major order, as a list of contiguous blocks in the source image's pixel format. + /// + /// The source image. + /// The type of the pixel. + /// The . + /// + /// Certain Image Processors may invalidate the returned and all it's buffers, + /// therefore it's not recommended to mutate the image while holding a reference to it's . + /// + public static IMemoryGroup GetPixelMemoryGroup(this Image source) + where TPixel : struct, IPixel + => source.Frames.RootFrame.GetPixelMemoryGroup(); + + /// + /// Gets the representation of the pixels as a in the source image's pixel format + /// stored in row major order, if the backing buffer is contiguous. + /// + /// The type of the pixel. + /// The source image. /// The + /// Thrown when the backing buffer is discontiguous. + [Obsolete( + @"GetPixelSpan might fail, because the backing buffer allowed to be discontiguous for large images. Use GetPixelMemoryGroup or GetPixelRowSpan instead!")] public static Span GetPixelSpan(this ImageFrame source) where TPixel : struct, IPixel - => source.GetPixelMemory().Span; + { + IMemoryGroup mg = source.GetPixelMemoryGroup(); + if (mg.Count > 1) + { + throw new InvalidOperationException($"GetPixelSpan is invalid, since the backing buffer of this {source.Width}x{source.Height} sized image is discontiguos!"); + } + + return mg.Single().Span; + } /// /// Gets the representation of the pixels as a of contiguous memory in the source image's pixel format @@ -65,6 +107,9 @@ namespace SixLabors.ImageSharp.Advanced /// The type of the pixel. /// The source. /// The + /// Thrown when the backing buffer is discontiguous. + [Obsolete( + @"GetPixelSpan might fail, because the backing buffer allowed to be discontiguous for large images. Use GetPixelMemoryGroup or GetPixelRowSpan instead!")] public static Span GetPixelSpan(this Image source) where TPixel : struct, IPixel => source.Frames.RootFrame.GetPixelSpan(); @@ -93,58 +138,6 @@ namespace SixLabors.ImageSharp.Advanced 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. - [Obsolete("This method will be removed in our next release! Please use MemoryMarshal.GetReference(source.GetPixelSpan())!")] - 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 contiguous memory area containing Width*Height TPixel elements laid out in row-major order. - /// - /// The Pixel format. - /// The source image - /// A pinnable reference the first root of the pixel buffer. - [Obsolete("This method will be removed in our next release! Please use MemoryMarshal.GetReference(source.GetPixelSpan())!")] - public static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(this Image source) - where TPixel : struct, IPixel - => ref source.Frames.RootFrame.DangerousGetPinnableReferenceToPixelBuffer(); - - /// - /// 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 - /// The - internal static Memory GetPixelMemory(this ImageFrame source) - where TPixel : struct, IPixel - { - return source.PixelBuffer.GetSingleMemory(); - } - - /// - /// 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 - /// The - internal static Memory GetPixelMemory(this Image source) - where TPixel : struct, IPixel - { - return source.Frames.RootFrame.GetPixelMemory(); - } - /// /// Gets the representation of the pixels as a of contiguous memory /// at row beginning from the the first pixel on that row. diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs index f6b51e8c5..548caa488 100644 --- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs +++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced var targetBuffer = new TPixel[image0.Width * image0.Height]; // Act: - Memory memory = image0.GetPixelMemory(); + Memory memory = image0.GetRootFramePixelBuffer().GetSingleMemory(); // Assert: Assert.Equal(image0.Width * image0.Height, memory.Length); @@ -56,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced using (var image1 = Image.WrapMemory(externalMemory, image0.Width, image0.Height)) { - Memory internalMemory = image1.GetPixelMemory(); + Memory internalMemory = image1.GetRootFramePixelBuffer().GetSingleMemory(); Assert.Equal(targetBuffer.Length, internalMemory.Length); Assert.True(Unsafe.AreSame(ref targetBuffer[0], ref internalMemory.Span[0])); @@ -120,29 +121,5 @@ namespace SixLabors.ImageSharp.Tests.Advanced } } } - - #pragma warning disable 0618 - - [Theory] - [WithTestPatternImages(131, 127, PixelTypes.Rgba32 | PixelTypes.Bgr24)] - public unsafe void DangerousGetPinnableReference_CopyToBuffer(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - var targetBuffer = new TPixel[image.Width * image.Height]; - - ref byte source = ref Unsafe.As(ref targetBuffer[0]); - ref byte dest = ref Unsafe.As(ref image.DangerousGetPinnableReferenceToPixelBuffer()); - fixed (byte* targetPtr = &source) - fixed (byte* pixelBasePtr = &dest) - { - uint dataSizeInBytes = (uint)(image.Width * image.Height * Unsafe.SizeOf()); - Unsafe.CopyBlock(targetPtr, pixelBasePtr, dataSizeInBytes); - } - - image.ComparePixelBufferTo(targetBuffer); - } - } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index 0cf3071a0..423309dfb 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -9,6 +9,7 @@ using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -116,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests using (var image = Image.WrapMemory(memory, bmp.Width, bmp.Height)) { - Assert.Equal(memory, image.GetPixelMemory()); + Assert.Equal(memory, image.GetRootFramePixelBuffer().GetSingleMemory()); image.GetPixelSpan().Fill(bg); for (var i = 10; i < 20; i++) { @@ -151,7 +152,7 @@ namespace SixLabors.ImageSharp.Tests using (var image = Image.WrapMemory(memoryManager, bmp.Width, bmp.Height)) { - Assert.Equal(memoryManager.Memory, image.GetPixelMemory()); + Assert.Equal(memoryManager.Memory, image.GetRootFramePixelBuffer().GetSingleMemory()); image.GetPixelSpan().Fill(bg); for (var i = 10; i < 20; i++)