@@ -16,8 +16,22 @@ namespace SixLabors.ImageSharp
1616 public abstract partial class Image
1717 {
1818 /// <summary>
19- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
20- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
19+ /// <para>
20+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
21+ /// an <see cref="Image{TPixel}"/> instance.
22+ /// </para>
23+ /// <para>
24+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
25+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
26+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
27+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
28+ /// </para>
29+ /// <para>
30+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
31+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
32+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
33+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
34+ /// </para>
2135 /// </summary>
2236 /// <typeparam name="TPixel">The pixel type</typeparam>
2337 /// <param name="configuration">The <see cref="Configuration"/></param>
@@ -45,8 +59,22 @@ public static Image<TPixel> WrapMemory<TPixel>(
4559 }
4660
4761 /// <summary>
48- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
49- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
62+ /// <para>
63+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
64+ /// an <see cref="Image{TPixel}"/> instance.
65+ /// </para>
66+ /// <para>
67+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
68+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
69+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
70+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
71+ /// </para>
72+ /// <para>
73+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
74+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
75+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
76+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
77+ /// </para>
5078 /// </summary>
5179 /// <typeparam name="TPixel">The pixel type</typeparam>
5280 /// <param name="configuration">The <see cref="Configuration"/></param>
@@ -64,9 +92,22 @@ public static Image<TPixel> WrapMemory<TPixel>(
6492 => WrapMemory ( configuration , pixelMemory , width , height , new ImageMetadata ( ) ) ;
6593
6694 /// <summary>
67- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
68- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
69- /// The memory is being observed, the caller remains responsible for managing it's lifecycle.
95+ /// <para>
96+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
97+ /// an <see cref="Image{TPixel}"/> instance.
98+ /// </para>
99+ /// <para>
100+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
101+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
102+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
103+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
104+ /// </para>
105+ /// <para>
106+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
107+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
108+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
109+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
110+ /// </para>
70111 /// </summary>
71112 /// <typeparam name="TPixel">The pixel type.</typeparam>
72113 /// <param name="pixelMemory">The pixel memory.</param>
@@ -154,8 +195,22 @@ public static Image<TPixel> WrapMemory<TPixel>(
154195 => WrapMemory ( Configuration . Default , pixelMemoryOwner , width , height ) ;
155196
156197 /// <summary>
157- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
158- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
198+ /// <para>
199+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
200+ /// an <see cref="Image{TPixel}"/> instance.
201+ /// </para>
202+ /// <para>
203+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
204+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
205+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
206+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
207+ /// </para>
208+ /// <para>
209+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
210+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
211+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
212+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
213+ /// </para>
159214 /// </summary>
160215 /// <typeparam name="TPixel">The pixel type</typeparam>
161216 /// <param name="configuration">The <see cref="Configuration"/></param>
@@ -186,8 +241,22 @@ public static Image<TPixel> WrapMemory<TPixel>(
186241 }
187242
188243 /// <summary>
189- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
190- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
244+ /// <para>
245+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
246+ /// an <see cref="Image{TPixel}"/> instance.
247+ /// </para>
248+ /// <para>
249+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
250+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
251+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
252+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
253+ /// </para>
254+ /// <para>
255+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
256+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
257+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
258+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
259+ /// </para>
191260 /// </summary>
192261 /// <typeparam name="TPixel">The pixel type</typeparam>
193262 /// <param name="configuration">The <see cref="Configuration"/></param>
@@ -205,9 +274,22 @@ public static Image<TPixel> WrapMemory<TPixel>(
205274 => WrapMemory < TPixel > ( configuration , byteMemory , width , height , new ImageMetadata ( ) ) ;
206275
207276 /// <summary>
208- /// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
209- /// allowing to view/manipulate it as an <see cref="Image{TPixel}"/> instance.
210- /// The memory is being observed, the caller remains responsible for managing it's lifecycle.
277+ /// <para>
278+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
279+ /// an <see cref="Image{TPixel}"/> instance.
280+ /// </para>
281+ /// <para>
282+ /// Please note: using this method does not transfer the ownership of the underlying buffer of the input <see cref="Memory{T}"/>
283+ /// to the new <see cref="Image{TPixel}"/> instance. This means that consumers of this method must ensure that the input buffer
284+ /// is either self-contained, (for example, a <see cref="Memory{T}"/> instance wrapping a new array that was
285+ /// created), or that the owning object is not disposed until the returned <see cref="Image{TPixel}"/> is disposed.
286+ /// </para>
287+ /// <para>
288+ /// If the input <see cref="Memory{T}"/> instance is one retrieved from an <see cref="IMemoryOwner{T}"/> instance
289+ /// rented from a memory pool (such as <see cref="MemoryPool{T}"/>), and that owning instance is disposed while the image is still
290+ /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other
291+ /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately.
292+ /// </para>
211293 /// </summary>
212294 /// <typeparam name="TPixel">The pixel type.</typeparam>
213295 /// <param name="byteMemory">The byte memory representing the pixel data.</param>
@@ -220,5 +302,128 @@ public static Image<TPixel> WrapMemory<TPixel>(
220302 int height )
221303 where TPixel : unmanaged, IPixel < TPixel >
222304 => WrapMemory < TPixel > ( Configuration . Default , byteMemory , width , height ) ;
305+
306+ /// <summary>
307+ /// <para>
308+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
309+ /// an <see cref="Image{TPixel}"/> instance.
310+ /// </para>
311+ /// <para>
312+ /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the
313+ /// pointer and that the lifetime of such a memory area is at least equal to that of the returned
314+ /// <see cref="Image{TPixel}"/> instance. For example, if the input pointer references an unmanaged memory area,
315+ /// callers must ensure that the memory area is not freed as long as the returned <see cref="Image{TPixel}"/> is
316+ /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers
317+ /// must ensure that objects will remain pinned as long as the <see cref="Image{TPixel}"/> instance is in use.
318+ /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes.
319+ /// </para>
320+ /// <para>
321+ /// Note also that if you have a <see cref="Memory{T}"/> or an array (which can be cast to <see cref="Memory{T}"/>) of
322+ /// either <see cref="byte"/> or <typeparamref name="TPixel"/> values, it is highly recommended to use one of the other
323+ /// available overloads of this method instead (such as <see cref="WrapMemory{TPixel}(Configuration, Memory{byte}, int, int)"/>
324+ /// or <see cref="WrapMemory{TPixel}(Configuration, Memory{TPixel}, int, int)"/>, to make the resulting code less error
325+ /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when
326+ /// doing interop or working with buffers that are located in unmanaged memory.
327+ /// </para>
328+ /// </summary>
329+ /// <typeparam name="TPixel">The pixel type</typeparam>
330+ /// <param name="configuration">The <see cref="Configuration"/></param>
331+ /// <param name="pointer">The pointer to the target memory buffer to wrap.</param>
332+ /// <param name="width">The width of the memory image.</param>
333+ /// <param name="height">The height of the memory image.</param>
334+ /// <param name="metadata">The <see cref="ImageMetadata"/>.</param>
335+ /// <exception cref="ArgumentNullException">The configuration is null.</exception>
336+ /// <exception cref="ArgumentNullException">The metadata is null.</exception>
337+ /// <returns>An <see cref="Image{TPixel}"/> instance</returns>
338+ public static unsafe Image < TPixel > WrapMemory < TPixel > (
339+ Configuration configuration ,
340+ void * pointer ,
341+ int width ,
342+ int height ,
343+ ImageMetadata metadata )
344+ where TPixel : unmanaged, IPixel < TPixel >
345+ {
346+ Guard . IsFalse ( pointer == null , nameof ( pointer ) , "Pointer must be not null" ) ;
347+ Guard . NotNull ( configuration , nameof ( configuration ) ) ;
348+ Guard . NotNull ( metadata , nameof ( metadata ) ) ;
349+
350+ var memoryManager = new UnmanagedMemoryManager < TPixel > ( pointer , width * height ) ;
351+
352+ var memorySource = MemoryGroup < TPixel > . Wrap ( memoryManager . Memory ) ;
353+ return new Image < TPixel > ( configuration , memorySource , width , height , metadata ) ;
354+ }
355+
356+ /// <summary>
357+ /// <para>
358+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
359+ /// an <see cref="Image{TPixel}"/> instance.
360+ /// </para>
361+ /// <para>
362+ /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the
363+ /// pointer and that the lifetime of such a memory area is at least equal to that of the returned
364+ /// <see cref="Image{TPixel}"/> instance. For example, if the input pointer references an unmanaged memory area,
365+ /// callers must ensure that the memory area is not freed as long as the returned <see cref="Image{TPixel}"/> is
366+ /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers
367+ /// must ensure that objects will remain pinned as long as the <see cref="Image{TPixel}"/> instance is in use.
368+ /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes.
369+ /// </para>
370+ /// <para>
371+ /// Note also that if you have a <see cref="Memory{T}"/> or an array (which can be cast to <see cref="Memory{T}"/>) of
372+ /// either <see cref="byte"/> or <typeparamref name="TPixel"/> values, it is highly recommended to use one of the other
373+ /// available overloads of this method instead (such as <see cref="WrapMemory{TPixel}(Configuration, Memory{byte}, int, int)"/>
374+ /// or <see cref="WrapMemory{TPixel}(Configuration, Memory{TPixel}, int, int)"/>, to make the resulting code less error
375+ /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when
376+ /// doing interop or working with buffers that are located in unmanaged memory.
377+ /// </para>
378+ /// </summary>
379+ /// <typeparam name="TPixel">The pixel type</typeparam>
380+ /// <param name="configuration">The <see cref="Configuration"/></param>
381+ /// <param name="pointer">The pointer to the target memory buffer to wrap.</param>
382+ /// <param name="width">The width of the memory image.</param>
383+ /// <param name="height">The height of the memory image.</param>
384+ /// <exception cref="ArgumentNullException">The configuration is null.</exception>
385+ /// <returns>An <see cref="Image{TPixel}"/> instance.</returns>
386+ public static unsafe Image < TPixel > WrapMemory < TPixel > (
387+ Configuration configuration ,
388+ void * pointer ,
389+ int width ,
390+ int height )
391+ where TPixel : unmanaged, IPixel < TPixel >
392+ => WrapMemory < TPixel > ( configuration , pointer , width , height , new ImageMetadata ( ) ) ;
393+
394+ /// <summary>
395+ /// <para>
396+ /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as
397+ /// an <see cref="Image{TPixel}"/> instance.
398+ /// </para>
399+ /// <para>
400+ /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the
401+ /// pointer and that the lifetime of such a memory area is at least equal to that of the returned
402+ /// <see cref="Image{TPixel}"/> instance. For example, if the input pointer references an unmanaged memory area,
403+ /// callers must ensure that the memory area is not freed as long as the returned <see cref="Image{TPixel}"/> is
404+ /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers
405+ /// must ensure that objects will remain pinned as long as the <see cref="Image{TPixel}"/> instance is in use.
406+ /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes.
407+ /// </para>
408+ /// <para>
409+ /// Note also that if you have a <see cref="Memory{T}"/> or an array (which can be cast to <see cref="Memory{T}"/>) of
410+ /// either <see cref="byte"/> or <typeparamref name="TPixel"/> values, it is highly recommended to use one of the other
411+ /// available overloads of this method instead (such as <see cref="WrapMemory{TPixel}(Configuration, Memory{byte}, int, int)"/>
412+ /// or <see cref="WrapMemory{TPixel}(Configuration, Memory{TPixel}, int, int)"/>, to make the resulting code less error
413+ /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when
414+ /// doing interop or working with buffers that are located in unmanaged memory.
415+ /// </para>
416+ /// </summary>
417+ /// <typeparam name="TPixel">The pixel type.</typeparam>
418+ /// <param name="pointer">The pointer to the target memory buffer to wrap.</param>
419+ /// <param name="width">The width of the memory image.</param>
420+ /// <param name="height">The height of the memory image.</param>
421+ /// <returns>An <see cref="Image{TPixel}"/> instance.</returns>
422+ public static unsafe Image < TPixel > WrapMemory < TPixel > (
423+ void * pointer ,
424+ int width ,
425+ int height )
426+ where TPixel : unmanaged, IPixel < TPixel >
427+ => WrapMemory < TPixel > ( Configuration . Default , pointer , width , height ) ;
223428 }
224429}
0 commit comments