diff --git a/src/NetVips/Internal/Vips.cs b/src/NetVips/Internal/Vips.cs
index 10740bcf..b7a97db4 100644
--- a/src/NetVips/Internal/Vips.cs
+++ b/src/NetVips/Internal/Vips.cs
@@ -295,6 +295,10 @@ internal static class VipsBlob
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_blob_get")]
internal static extern IntPtr Get(VipsBlobManaged blob, out UIntPtr length);
+
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_blob_copy")]
+ internal static extern unsafe VipsBlobManaged Copy(void* data, UIntPtr length);
}
internal static class VipsArea
@@ -422,6 +426,12 @@ internal static class VipsImage
internal static extern IntPtr NewFromMemory(IntPtr data, UIntPtr size, int width, int height,
int bands, BandFormat format);
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
+ EntryPoint = "vips_image_new_from_memory")]
+ internal static extern unsafe IntPtr NewFromMemory(void* data, UIntPtr size, int width, int height,
+ int bands, BandFormat format);
+
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_from_memory_copy")]
@@ -582,6 +592,11 @@ internal static class VipsForeign
EntryPoint = "vips_foreign_find_load_buffer")]
internal static extern IntPtr FindLoadBuffer(IntPtr data, ulong size);
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
+ EntryPoint = "vips_foreign_find_load_buffer")]
+ internal static extern unsafe IntPtr FindLoadBuffer(void* data, ulong size);
+
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load_source")]
@@ -637,6 +652,11 @@ internal static class VipsSource
EntryPoint = "vips_source_new_from_file")]
internal static extern IntPtr NewFromFile(byte[] filename);
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
+ EntryPoint = "vips_source_new_from_blob")]
+ internal static extern IntPtr NewFromBlob(VipsBlobManaged blob);
+
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_new_from_memory")]
diff --git a/src/NetVips/NetVips.csproj b/src/NetVips/NetVips.csproj
index d2c763e9..1a46cd08 100644
--- a/src/NetVips/NetVips.csproj
+++ b/src/NetVips/NetVips.csproj
@@ -11,6 +11,7 @@
x64;x86;ARM64;ARM32
true
+ true
false
true
true
diff --git a/src/NetVips/Source.cs b/src/NetVips/Source.cs
index 7695020f..cddb03e1 100644
--- a/src/NetVips/Source.cs
+++ b/src/NetVips/Source.cs
@@ -7,7 +7,7 @@ namespace NetVips
///
/// An input connection.
///
- public class Source : Connection
+ public partial class Source : Connection
{
// private static Logger logger = LogManager.GetCurrentClassLogger();
diff --git a/src/NetVips/net6.0/Image.cs b/src/NetVips/net6.0/Image.cs
new file mode 100644
index 00000000..d26870c3
--- /dev/null
+++ b/src/NetVips/net6.0/Image.cs
@@ -0,0 +1,137 @@
+#if NET6_0_OR_GREATER
+
+namespace NetVips
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using Internal;
+
+ ///
+ /// Wrap a object.
+ ///
+ public partial class Image
+ {
+ #region helpers
+
+ ///
+ /// Find the name of the load operation vips will use to load a buffer.
+ ///
+ ///
+ /// For example "VipsForeignLoadJpegBuffer". You can use this to work out what
+ /// options to pass to .
+ ///
+ /// The buffer to test.
+ /// Length of the buffer.
+ /// The name of the load operation, or .
+ internal static unsafe string FindLoadBuffer(void* data, ulong size) =>
+ Marshal.PtrToStringAnsi(VipsForeign.FindLoadBuffer(data, size));
+
+ ///
+ /// Find the name of the load operation vips will use to load a buffer.
+ ///
+ ///
+ /// For example "VipsForeignLoadJpegBuffer". You can use this to work out what
+ /// options to pass to .
+ ///
+ /// The buffer to test.
+ /// The name of the load operation, or .
+ public static unsafe string FindLoadBuffer(ReadOnlySpan data)
+ {
+ fixed (byte* dataFixed = data)
+ {
+ return FindLoadBuffer(dataFixed, (ulong)data.Length);
+ }
+ }
+
+ #endregion
+
+ #region constructors
+
+ ///
+ /// Load a formatted image from memory.
+ ///
+ ///
+ /// This behaves exactly as , but the image is
+ /// loaded from the memory object rather than from a file. The memory
+ /// object can be a string or buffer.
+ ///
+ /// The memory object to load the image from.
+ /// Load options as a string. Use for no options.
+ /// Hint the expected access pattern for the image.
+ /// The type of error that will cause load to fail. By
+ /// default, loaders are permissive, that is, .
+ /// Optional options that depend on the load operation.
+ /// A new .
+ /// If unable to load from .
+ public static unsafe Image NewFromBuffer(
+ ReadOnlySpan data,
+ string strOptions = "",
+ Enums.Access? access = null,
+ Enums.FailOn? failOn = null,
+ VOption kwargs = null)
+ {
+ fixed (byte* dataFixed = data)
+ {
+ var operationName = FindLoadBuffer(dataFixed, (ulong)data.Length);
+ if (operationName == null)
+ {
+ throw new VipsException("unable to load from buffer");
+ }
+
+ var options = new VOption();
+ if (kwargs != null)
+ {
+ options.Merge(kwargs);
+ }
+
+ options.AddIfPresent(nameof(access), access);
+ options.AddFailOn(failOn);
+
+ options.Add("string_options", strOptions);
+
+ using var blob = Internal.VipsBlob.Copy(dataFixed, (UIntPtr)data.Length);
+ return Operation.Call(operationName, options, blob) as Image;
+ }
+ }
+
+ ///
+ /// Wrap an image around a memory array.
+ ///
+ /// A .
+ /// Image width in pixels.
+ /// Image height in pixels.
+ /// Number of bands.
+ /// Band format.
+ /// A new .
+ /// If unable to make image from .
+ public static unsafe Image NewFromMemory(
+ ReadOnlyMemory data,
+ int width,
+ int height,
+ int bands,
+ Enums.BandFormat format) where T : unmanaged
+ {
+ var handle = data.Pin();
+ var vi = VipsImage.NewFromMemory(handle.Pointer, (UIntPtr)data.Length, width, height, bands,
+ format);
+
+ if (vi == IntPtr.Zero)
+ {
+ handle.Dispose();
+
+ throw new VipsException("unable to make image from memory");
+ }
+
+ var image = new Image(vi) { MemoryPressure = data.Length };
+
+ // Need to release the pinned MemoryHandle when the image is closed.
+ image.OnPostClose += () => handle.Dispose();
+
+ return image;
+ }
+
+ #endregion
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/src/NetVips/net6.0/Source.cs b/src/NetVips/net6.0/Source.cs
new file mode 100644
index 00000000..16763d7b
--- /dev/null
+++ b/src/NetVips/net6.0/Source.cs
@@ -0,0 +1,43 @@
+#if NET6_0_OR_GREATER
+
+namespace NetVips
+{
+ using System;
+
+ ///
+ /// An input connection.
+ ///
+ public partial class Source
+ {
+ ///
+ /// Make a new source from a memory object.
+ ///
+ ///
+ /// Make a new source that is attached to the memory object. For example:
+ ///
+ /// using var source = Source.NewFromMemory(data);
+ ///
+ /// You can pass this source to (for example) .
+ ///
+ /// The memory object.
+ /// A new .
+ /// If unable to create a new from .
+ public static unsafe Source NewFromMemory(ReadOnlySpan data)
+ {
+ fixed (byte* dataFixed = data)
+ {
+ using var blob = Internal.VipsBlob.Copy(dataFixed, (UIntPtr)data.Length);
+ var pointer = Internal.VipsSource.NewFromBlob(blob);
+
+ if (pointer == IntPtr.Zero)
+ {
+ throw new VipsException("can't create input source from memory");
+ }
+
+ return new Source(pointer);
+ }
+ }
+ }
+}
+
+#endif
\ No newline at end of file