#if NET6_0_OR_GREATER using System; using System.Runtime.InteropServices; using NetVips.Internal; namespace NetVips; /// /// 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 . private 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); var ptr = Internal.VipsBlob.Copy(dataFixed, (nuint)data.Length); if (ptr == IntPtr.Zero) { throw new VipsException("unable to load from buffer"); } using var blob = new VipsBlob(ptr); 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, (nuint)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; } /// /// Like , but /// for , so we must copy as it could be allocated on the stack. /// /// 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 NewFromMemoryCopy( ReadOnlySpan data, int width, int height, int bands, Enums.BandFormat format) where T : unmanaged { fixed (T* dataFixed = data) { var vi = VipsImage.NewFromMemoryCopy(dataFixed, (nuint)data.Length, width, height, bands, format); if (vi == IntPtr.Zero) { throw new VipsException("unable to make image from memory"); } return new Image(vi) { MemoryPressure = data.Length }; } } #endregion } #endif