#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