From 95f1f5a60a5778c62280783b79e64a9b030ac586 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 8 Nov 2020 13:06:28 +0100 Subject: [PATCH] Add unowned Image.WrapMemory(void*) overloads --- src/ImageSharp/Image.WrapMemory.cs | 66 +++++++++++++++++++ src/ImageSharp/Memory/ByteMemoryManager{T}.cs | 1 + .../Memory/UnmanagedMemoryManager{T}.cs | 60 +++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index d89c44dc56..b080c78887 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -220,5 +220,71 @@ namespace SixLabors.ImageSharp int height) where TPixel : unmanaged, IPixel => WrapMemory(Configuration.Default, byteMemory, width, height); + + /// + /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// allowing to view/manipulate it as an instance. + /// + /// The pixel type + /// The + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// The . + /// The configuration is null. + /// The metadata is null. + /// An instance + public static unsafe Image WrapMemory( + Configuration configuration, + void* pointer, + int width, + int height, + ImageMetadata metadata) + where TPixel : unmanaged, IPixel + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(metadata, nameof(metadata)); + + var memoryManager = new UnmanagedMemoryManager(pointer, width * height); + + var memorySource = MemoryGroup.Wrap(memoryManager.Memory); + return new Image(configuration, memorySource, width, height, metadata); + } + + /// + /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// allowing to view/manipulate it as an instance. + /// + /// The pixel type + /// The + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// The configuration is null. + /// An instance. + public static unsafe Image WrapMemory( + Configuration configuration, + void* pointer, + int width, + int height) + where TPixel : unmanaged, IPixel + => WrapMemory(configuration, pointer, width, height, new ImageMetadata()); + + /// + /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// allowing to view/manipulate it as an instance. + /// The memory is being observed, the caller remains responsible for managing it's lifecycle. + /// + /// The pixel type. + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// An instance. + public static unsafe Image WrapMemory( + void* pointer, + int width, + int height) + where TPixel : unmanaged, IPixel + => WrapMemory(Configuration.Default, pointer, width, height); } } diff --git a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs index 223709df65..1731639582 100644 --- a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs +++ b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs @@ -1,5 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. + using System; using System.Buffers; using System.Runtime.CompilerServices; diff --git a/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs b/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs new file mode 100644 index 0000000000..58eaee320a --- /dev/null +++ b/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs @@ -0,0 +1,60 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +namespace SixLabors.ImageSharp.Memory +{ + /// + /// A custom that can wrap a rawpointer to a buffer of a specified type. + /// + /// The value type to use when casting the wrapped instance. + /// This manager doesn't own the memory buffer that it points to. + internal sealed unsafe class UnmanagedMemoryManager : MemoryManager + where T : unmanaged + { + /// + /// The pointer to the memory buffer. + /// + private readonly void* pointer; + + /// + /// The length of the memory area. + /// + private readonly int length; + + /// + /// Initializes a new instance of the class. + /// + /// The pointer to the memory buffer. + /// The length of the memory area. + public UnmanagedMemoryManager(void* pointer, int length) + { + this.pointer = pointer; + this.length = length; + } + + /// + protected override void Dispose(bool disposing) + { + } + + /// + public override Span GetSpan() + { + return new Span(this.pointer, this.length); + } + + /// + public override MemoryHandle Pin(int elementIndex = 0) + { + return new MemoryHandle(((T*)this.pointer) + elementIndex); + } + + /// + public override void Unpin() + { + } + } +}