// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using Xunit; namespace SixLabors.ImageSharp.Tests.Advanced { public class AdvancedImageExtensionsTests { public class GetPixelMemory { [Theory] [WithSolidFilledImages(1, 1, "Red", PixelTypes.Rgba32)] [WithTestPatternImages(131, 127, PixelTypes.Rgba32 | PixelTypes.Bgr24)] public void WhenMemoryIsOwned(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image0 = provider.GetImage()) { var targetBuffer = new TPixel[image0.Width * image0.Height]; // Act: Memory memory = image0.GetPixelMemory(); // Assert: Assert.Equal(image0.Width * image0.Height, memory.Length); memory.Span.CopyTo(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)] 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); } } } }