vendoring NetVips

This commit is contained in:
Renjaya Raga Zenta 2025-07-31 00:17:59 +07:00
parent 36a0f8d39c
commit 33e9d5f43a
41 changed files with 21749 additions and 0 deletions

49
vendor/NetVips/Cache.cs vendored Normal file
View file

@ -0,0 +1,49 @@
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// A class around libvips' operation cache.
/// </summary>
public static class Cache
{
/// <summary>
/// Gets or sets the maximum number of operations libvips keeps in cache.
/// </summary>
public static int Max
{
get => Vips.CacheGetMax();
set => Vips.CacheSetMax(value);
}
/// <summary>
/// Gets or sets the maximum amount of tracked memory allowed.
/// </summary>
public static ulong MaxMem
{
get => Vips.CacheGetMaxMem();
set => Vips.CacheSetMaxMem(value);
}
/// <summary>
/// Gets or sets the maximum amount of tracked files allowed.
/// </summary>
public static int MaxFiles
{
get => Vips.CacheGetMaxFiles();
set => Vips.CacheSetMaxFiles(value);
}
/// <summary>
/// Gets the current number of operations in cache.
/// </summary>
public static int Size => Vips.CacheGetSize();
/// <summary>
/// Enable or disable libvips cache tracing.
/// </summary>
public static bool Trace
{
set => Vips.CacheSetTrace(value);
}
}

32
vendor/NetVips/Connection.cs vendored Normal file
View file

@ -0,0 +1,32 @@
namespace NetVips;
/// <summary>
/// The abstract base Connection class.
/// </summary>
public abstract class Connection : VipsObject
{
/// <inheritdoc cref="GObject"/>
internal Connection(nint pointer) : base(pointer)
{
}
/// <summary>
/// Get the filename associated with a connection. Return <see langword="null"/> if there
/// is no associated file.
/// </summary>
/// <returns>The filename associated with this connection or <see langword="null"/>.</returns>
public string GetFileName()
{
return Internal.VipsConnection.FileName(this).ToUtf8String();
}
/// <summary>
/// Make a human-readable name for a connection suitable for error
/// messages.
/// </summary>
/// <returns>The human-readable name for this connection.</returns>
public string GetNick()
{
return Internal.VipsConnection.Nick(this).ToUtf8String();
}
}

1312
vendor/NetVips/Enums.cs vendored Normal file

File diff suppressed because it is too large Load diff

289
vendor/NetVips/ExtensionMethods.cs vendored Normal file
View file

@ -0,0 +1,289 @@
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Text;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Useful extension methods that we use in our codebase.
/// </summary>
internal static class ExtensionMethods
{
/// <summary>
/// Removes the element with the specified key from the <see cref="VOption"/>
/// and retrieves the value to <paramref name="target"/>.
/// </summary>
/// <param name="self">The <see cref="VOption"/> to remove from.</param>
/// <param name="key">>The key of the element to remove.</param>
/// <param name="target">The target to retrieve the value to.</param>
/// <returns><see langword="true"/> if the element is successfully removed; otherwise, <see langword="false"/>.</returns>
internal static bool Remove(this VOption self, string key, out object target)
{
self.TryGetValue(key, out target);
return self.Remove(key);
}
/// <summary>
/// Merges 2 <see cref="VOption"/>s.
/// </summary>
/// <param name="self">The <see cref="VOption"/> to merge into.</param>
/// <param name="merge">The <see cref="VOption"/> to merge from.</param>
internal static void Merge(this VOption self, VOption merge)
{
foreach (var item in merge)
{
self[item.Key] = item.Value;
}
}
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <param name="image">A <see cref="Image"/> used as guide.</param>
/// <param name="operationName">Operation name.</param>
/// <returns>A new object.</returns>
internal static object Call(this Image image, string operationName) =>
Operation.Call(operationName, null, image);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <param name="image">A <see cref="Image"/> used as guide.</param>
/// <param name="operationName">Operation name.</param>
/// <param name="args">An arbitrary number and variety of arguments.</param>
/// <returns>A new object.</returns>
internal static object Call(this Image image, string operationName, params object[] args) =>
Operation.Call(operationName, null, image, args);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <param name="image">A <see cref="Image"/> used as guide.</param>
/// <param name="operationName">Operation name.</param>
/// <param name="kwargs">Optional arguments.</param>
/// <returns>A new object.</returns>
internal static object Call(this Image image, string operationName, VOption kwargs) =>
Operation.Call(operationName, kwargs, image);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <param name="image">A <see cref="Image"/> used as guide.</param>
/// <param name="operationName">Operation name.</param>
/// <param name="kwargs">Optional arguments.</param>
/// <param name="args">An arbitrary number and variety of arguments.</param>
/// <returns>A new object.</returns>
internal static object Call(this Image image, string operationName, VOption kwargs, params object[] args) =>
Operation.Call(operationName, kwargs, image, args);
/// <summary>
/// Prepends <paramref name="image"/> to <paramref name="args"/>.
/// </summary>
/// <param name="args">The <see cref="Image"/> array.</param>
/// <param name="image">The <see cref="Image"/> to prepend to <paramref name="args"/>.</param>
/// <returns>A new object array.</returns>
internal static object[] PrependImage<T>(this T[] args, Image image)
{
if (args == null)
{
return new object[] { image };
}
var newValues = new object[args.Length + 1];
newValues[0] = image;
Array.Copy(args, 0, newValues, 1, args.Length);
return newValues;
}
/// <summary>
/// Marshals a GLib UTF8 char* to a managed string.
/// </summary>
/// <param name="utf8Str">Pointer to the GLib string.</param>
/// <param name="freePtr">If set to <see langword="true"/>, free the GLib string.</param>
/// <param name="size">Size of the GLib string, use 0 to read until the null character.</param>
/// <returns>The managed string.</returns>
internal static string ToUtf8String(this nint utf8Str, bool freePtr = false, int size = 0)
{
if (utf8Str == IntPtr.Zero)
{
return null;
}
if (size == 0)
{
while (Marshal.ReadByte(utf8Str, size) != 0)
{
++size;
}
}
if (size == 0)
{
if (freePtr)
{
GLib.GFree(utf8Str);
}
return string.Empty;
}
var bytes = ArrayPool<byte>.Shared.Rent(size);
try
{
Marshal.Copy(utf8Str, bytes, 0, size);
return Encoding.UTF8.GetString(bytes, 0, size);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
if (freePtr)
{
GLib.GFree(utf8Str);
}
}
}
/// <summary>
/// Convert bytes to human readable format.
/// </summary>
/// <param name="value">The number of bytes.</param>
/// <returns>The readable format of the bytes.</returns>
internal static string ToReadableBytes(this ulong value)
{
string[] sizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
var i = 0;
decimal dValue = value;
while (Math.Round(dValue, 2) >= 1000)
{
dValue /= 1024;
i++;
}
return $"{dValue:n2} {sizeSuffixes[i]}";
}
/// <summary>
/// Negate all elements in an array.
/// </summary>
/// <param name="array">An array of doubles.</param>
/// <returns>The negated array.</returns>
internal static double[] Negate(this double[] array)
{
for (var i = 0; i < array.Length; i++)
{
array[i] *= -1;
}
return array;
}
/// <summary>
/// Negate all elements in an array.
/// </summary>
/// <remarks>
/// It will output an array of doubles instead of integers.
/// </remarks>
/// <param name="array">An array of integers.</param>
/// <returns>The negated array.</returns>
internal static double[] Negate(this int[] array)
{
var doubles = new double[array.Length];
for (var i = 0; i < array.Length; i++)
{
ref var value = ref doubles[i];
value = array[i] * -1;
}
return doubles;
}
/// <summary>
/// Invert all elements in an array.
/// </summary>
/// <param name="array">An array of doubles.</param>
/// <returns>The inverted array.</returns>
internal static double[] Invert(this double[] array)
{
for (var i = 0; i < array.Length; i++)
{
array[i] = 1.0 / array[i];
}
return array;
}
/// <summary>
/// Invert all elements in an array.
/// </summary>
/// <remarks>
/// It will output an array of doubles instead of integers.
/// </remarks>
/// <param name="array">An array of integers.</param>
/// <returns>The inverted array.</returns>
internal static double[] Invert(this int[] array)
{
var doubles = new double[array.Length];
for (var i = 0; i < array.Length; i++)
{
ref var value = ref doubles[i];
value = 1.0 / array[i];
}
return doubles;
}
/// <summary>
/// Compatibility method to call loaders with the <see cref="Enums.FailOn"/> enum.
/// </summary>
/// <param name="options">The optional arguments for the loader.</param>
/// <param name="failOn">The optional <see cref="Enums.FailOn"/> parameter.</param>
internal static void AddFailOn(this VOption options, Enums.FailOn? failOn = null)
{
if (!failOn.HasValue)
{
return;
}
if (NetVips.AtLeastLibvips(8, 12))
{
options.Add("fail_on", failOn);
}
else
{
// The deprecated "fail" param was at the highest sensitivity (>= warning),
// but for compat it would be more correct to set this to true only when
// a non-permissive enum is given (> none).
options.Add("fail", failOn > Enums.FailOn.None);
}
}
/// <summary>
/// Compatibility method to call savers with the <see cref="Enums.ForeignKeep"/> enum.
/// </summary>
/// <param name="options">The optional arguments for the saver.</param>
/// <param name="keep">The optional <see cref="Enums.ForeignKeep"/> parameter.</param>
/// <param name="isDzsave">Whether this operation is <see cref="Image.Dzsave"/>-like.</param>
internal static void AddForeignKeep(this VOption options, Enums.ForeignKeep? keep = null, bool isDzsave = false)
{
if (!keep.HasValue)
{
return;
}
if (NetVips.AtLeastLibvips(8, 15))
{
options.Add(nameof(keep), keep);
}
else if (isDzsave)
{
options.Add("no_strip", keep != Enums.ForeignKeep.None);
}
else
{
options.Add("strip", keep == Enums.ForeignKeep.None);
}
}
}

198
vendor/NetVips/GObject.cs vendored Normal file
View file

@ -0,0 +1,198 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using NetVips.Internal;
using GSignalMatchType = NetVips.Internal.Enums.GSignalMatchType;
namespace NetVips;
/// <summary>
/// Manage <see cref="Internal.GObject"/> lifetime.
/// </summary>
public class GObject : SafeHandle
{
/// <summary>
/// We have to record all of the <see cref="SignalConnect{T}"/> delegates to
/// prevent them from being re-located or disposed of by the garbage collector.
/// </summary>
/// <remarks>
/// All recorded delegates are freed in <see cref="ReleaseDelegates"/>.
/// </remarks>
private readonly ICollection<GCHandle> _handles = new List<GCHandle>();
/// <summary>
/// Hint of how much native memory is actually occupied by the object.
/// </summary>
internal long MemoryPressure;
// Handy for debugging
// public static int NObjects;
/// <summary>
/// Initializes a new instance of the <see cref="GObject"/> class
/// with the specified pointer to wrap around.
/// </summary>
/// <remarks>
/// Wraps a GObject instance around an underlying GValue. When the
/// instance is garbage-collected, the underlying object is unreferenced.
/// </remarks>
/// <param name="pointer">The pointer to wrap around.</param>
internal GObject(nint pointer) : base(IntPtr.Zero, true)
{
// record the pointer we were given to manage
SetHandle(pointer);
// NObjects++;
}
/// <summary>
/// Connects a callback function (<paramref name="callback"/>) to a signal on this object.
/// </summary>
/// <remarks>
/// The callback will be triggered every time this signal is issued on this instance.
/// </remarks>
/// <typeparam name="T">The type of the callback to connect.</typeparam>
/// <param name="detailedSignal">A string of the form "signal-name::detail".</param>
/// <param name="callback">The callback to connect.</param>
/// <param name="data">Data to pass to handler calls.</param>
/// <returns>The handler id.</returns>
/// <exception cref="T:System.ArgumentException">If it failed to connect the signal.</exception>
public ulong SignalConnect<T>(string detailedSignal, T callback, nint data = default)
where T : notnull
{
// add a weak reference callback to ensure all handles are released on finalization
if (_handles.Count == 0)
{
GWeakNotify notify = ReleaseDelegates;
var notifyHandle = GCHandle.Alloc(notify);
Internal.GObject.WeakRef(this, notify, GCHandle.ToIntPtr(notifyHandle));
}
// prevent the delegate from being re-located or disposed of by the garbage collector
var delegateHandle = GCHandle.Alloc(callback);
_handles.Add(delegateHandle);
var cHandler = Marshal.GetFunctionPointerForDelegate(callback);
var ret = GSignal.ConnectData(this, detailedSignal, cHandler, data, null, default);
if (ret == 0)
{
throw new ArgumentException("Failed to connect signal " + detailedSignal);
}
return ret;
}
/// <summary>
/// Disconnects a handler from this object.
/// </summary>
/// <remarks>
/// If the <paramref name="handlerId"/> is 0 then this function does nothing.
/// </remarks>
/// <param name="handlerId">Handler id of the handler to be disconnected.</param>
public void SignalHandlerDisconnect(ulong handlerId)
{
if (handlerId != 0)
{
GSignal.HandlerDisconnect(this, handlerId);
}
}
/// <summary>
/// Disconnects all handlers from this object that match <paramref name="func"/> and
/// <paramref name="data"/>.
/// </summary>
/// <typeparam name="T">The type of the func.</typeparam>
/// <param name="func">The func of the handlers.</param>
/// <param name="data">The data of the handlers.</param>
/// <returns>The number of handlers that matched.</returns>
public uint SignalHandlersDisconnectByFunc<T>(T func, nint data = default)
where T : notnull
{
var funcPtr = Marshal.GetFunctionPointerForDelegate(func);
return GSignal.HandlersDisconnectMatched(this,
GSignalMatchType.G_SIGNAL_MATCH_FUNC | GSignalMatchType.G_SIGNAL_MATCH_DATA,
0, 0, IntPtr.Zero, funcPtr, data);
}
/// <summary>
/// Disconnects all handlers from this object that match <paramref name="data"/>.
/// </summary>
/// <param name="data">The data of the handlers.</param>
/// <returns>The number of handlers that matched.</returns>
public uint SignalHandlersDisconnectByData(nint data)
{
return GSignal.HandlersDisconnectMatched(this,
GSignalMatchType.G_SIGNAL_MATCH_DATA,
0, 0, IntPtr.Zero, IntPtr.Zero, data);
}
/// <summary>
/// Decreases the reference count of object.
/// When its reference count drops to 0, the object is finalized (i.e. its memory is freed).
/// </summary>
/// <returns><see langword="true"/> if the handle is released successfully; otherwise,
/// in the event of a catastrophic failure, <see langword="false"/>.</returns>
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
Internal.GObject.Unref(handle);
}
// NObjects--;
return true;
}
/// <summary>
/// Release all the <see cref="SignalConnect{T}"/> delegates by this object on finalization.
/// </summary>
/// <remarks>
/// This function is only called when <see cref="SignalConnect{T}"/> was used on this object.
/// </remarks>
/// <param name="data">Data that was provided when the weak reference was established.</param>
/// <param name="objectPointer">The object being disposed.</param>
internal void ReleaseDelegates(nint data, nint objectPointer)
{
foreach (var gcHandle in _handles)
{
if (gcHandle.IsAllocated)
{
gcHandle.Free();
}
}
// All GCHandles are free'd. Clear the list to prevent inadvertent use.
_handles.Clear();
// Free the GCHandle used by this GWeakNotify
var notifyHandle = GCHandle.FromIntPtr(data);
if (notifyHandle.IsAllocated)
{
notifyHandle.Free();
}
}
/// <summary>
/// Increases the reference count of object.
/// </summary>
internal nint ObjectRef()
{
return Internal.GObject.Ref(handle);
}
/// <summary>
/// Gets a value indicating whether the handle is invalid.
/// </summary>
/// <returns><see langword="true"/> if the handle is not valid; otherwise, <see langword="false"/>.</returns>
public override bool IsInvalid => handle == IntPtr.Zero;
/// <summary>
/// Get the reference count of object. Handy for debugging.
/// </summary>
internal uint RefCount => Marshal.PtrToStructure<Internal.GObject.Struct>(handle).RefCount;
// Do not provide a finalizer - SafeHandle's critical finalizer will
// call ReleaseHandle for us.
}

513
vendor/NetVips/GValue.cs vendored Normal file
View file

@ -0,0 +1,513 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Wrap <see cref="Internal.GValue"/> in a C# class.
/// </summary>
/// <remarks>
/// This class wraps <see cref="Internal.GValue"/> in a convenient interface. You can use
/// instances of this class to get and set <see cref="GObject"/> properties.
///
/// On construction, <see cref="Internal.GValue"/> is all zero (empty). You can pass it to
/// a get function to have it filled by <see cref="GObject"/>, or use init to
/// set a type, set to set a value, then use it to set an object property.
///
/// GValue lifetime is managed automatically.
/// </remarks>
public class GValue : IDisposable
{
/// <summary>
/// The specified struct to wrap around.
/// </summary>
internal Internal.GValue.Struct Struct;
/// <summary>
/// Track whether <see cref="O:Dispose"/> has been called.
/// </summary>
private bool _disposed;
/// <summary>
/// Shift value used in converting numbers to type IDs.
/// </summary>
private const int FundamentalShift = 2;
// look up some common gtypes at init for speed
/// <summary>
/// The fundamental type corresponding to gboolean.
/// </summary>
public static readonly nint GBoolType = 5 << FundamentalShift;
/// <summary>
/// The fundamental type corresponding to gint.
/// </summary>
public static readonly nint GIntType = 6 << FundamentalShift;
/// <summary>
/// The fundamental type corresponding to guint64.
/// </summary>
public static readonly nint GUint64Type = 11 << FundamentalShift;
/// <summary>
/// The fundamental type from which all enumeration types are derived.
/// </summary>
public static readonly nint GEnumType = 12 << FundamentalShift;
/// <summary>
/// The fundamental type from which all flags types are derived.
/// </summary>
public static readonly nint GFlagsType = 13 << FundamentalShift;
/// <summary>
/// The fundamental type corresponding to gdouble.
/// </summary>
public static readonly nint GDoubleType = 15 << FundamentalShift;
/// <summary>
/// The fundamental type corresponding to null-terminated C strings.
/// </summary>
public static readonly nint GStrType = 16 << FundamentalShift;
/// <summary>
/// The fundamental type for GObject.
/// </summary>
public static readonly nint GObjectType = 20 << FundamentalShift;
/// <summary>
/// The fundamental type for VipsImage.
/// </summary>
public static readonly nint ImageType = NetVips.TypeFromName("VipsImage");
/// <summary>
/// The fundamental type for VipsArrayInt.
/// </summary>
public static readonly nint ArrayIntType = NetVips.TypeFromName("VipsArrayInt");
/// <summary>
/// The fundamental type for VipsArrayDouble.
/// </summary>
public static readonly nint ArrayDoubleType = NetVips.TypeFromName("VipsArrayDouble");
/// <summary>
/// The fundamental type for VipsArrayImage.
/// </summary>
public static readonly nint ArrayImageType = NetVips.TypeFromName("VipsArrayImage");
/// <summary>
/// The fundamental type for VipsRefString.
/// </summary>
public static readonly nint RefStrType = NetVips.TypeFromName("VipsRefString");
/// <summary>
/// The fundamental type for VipsBlob.
/// </summary>
public static readonly nint BlobType = NetVips.TypeFromName("VipsBlob");
/// <summary>
/// The fundamental type for VipsBlendMode. See <see cref="Enums.BlendMode"/>.
/// </summary>
public static readonly nint BlendModeType;
/// <summary>
/// The fundamental type for VipsSource. See <see cref="Source"/>.
/// </summary>
public static readonly nint SourceType;
/// <summary>
/// The fundamental type for VipsTarget. See <see cref="Target"/>.
/// </summary>
public static readonly nint TargetType;
/// <summary>
/// Hint of how much native memory is actually occupied by the object.
/// </summary>
private long _memoryPressure;
static GValue()
{
if (NetVips.AtLeastLibvips(8, 6))
{
BlendModeType = Vips.BlendModeGetType();
}
if (NetVips.AtLeastLibvips(8, 9))
{
SourceType = NetVips.TypeFromName("VipsSource");
TargetType = NetVips.TypeFromName("VipsTarget");
}
}
/// <summary>
/// Initializes a new instance of the <see cref="GValue"/> class.
/// </summary>
public GValue()
{
Struct = new Internal.GValue.Struct();
}
/// <summary>
/// Initializes a new instance of the <see cref="GValue"/> class
/// with the specified struct to wrap around.
/// </summary>
/// <param name="value">The specified struct to wrap around.</param>
internal GValue(Internal.GValue.Struct value)
{
Struct = value;
}
/// <summary>
/// Set the type of a GValue.
/// </summary>
/// <remarks>
/// GValues have a set type, fixed at creation time. Use SetType to set
/// the type of a GValue before assigning to it.
///
/// GTypes are 32 or 64-bit integers (depending on the platform). See
/// TypeFind.
/// </remarks>
/// <param name="gtype">Type the GValue should hold values of.</param>
public void SetType(nint gtype)
{
Internal.GValue.Init(ref Struct, gtype);
}
/// <summary>
/// Ensure that the GC knows the true cost of the object during collection.
/// </summary>
/// <remarks>
/// If the object is actually bigger than the managed size reflects, it may
/// be a candidate for quick(er) collection.
/// </remarks>
/// <param name="bytesAllocated">The amount of unmanaged memory that has been allocated.</param>
private void AddMemoryPressure(long bytesAllocated)
{
if (bytesAllocated <= 0)
{
return;
}
GC.AddMemoryPressure(bytesAllocated);
_memoryPressure += bytesAllocated;
}
/// <summary>
/// Set a GValue.
/// </summary>
/// <remarks>
/// The value is converted to the type of the GValue, if possible, and
/// assigned.
/// </remarks>
/// <param name="value">Value to be set.</param>
public void Set(object value)
{
var gtype = GetTypeOf();
var fundamental = GType.Fundamental(gtype);
if (gtype == GBoolType)
{
Internal.GValue.SetBoolean(ref Struct, Convert.ToBoolean(value));
}
else if (gtype == GIntType)
{
Internal.GValue.SetInt(ref Struct, Convert.ToInt32(value));
}
else if (gtype == GUint64Type)
{
Internal.GValue.SetUint64(ref Struct, Convert.ToUInt64(value));
}
else if (gtype == GDoubleType)
{
Internal.GValue.SetDouble(ref Struct, Convert.ToDouble(value));
}
else if (fundamental == GEnumType)
{
Internal.GValue.SetEnum(ref Struct, Convert.ToInt32(value));
}
else if (fundamental == GFlagsType)
{
Internal.GValue.SetFlags(ref Struct, Convert.ToUInt32(value));
}
else if (gtype == GStrType)
{
var bytes = Encoding.UTF8.GetBytes(Convert.ToString(value) +
char.MinValue); // Ensure null-terminated string
Internal.GValue.SetString(ref Struct, bytes);
}
else if (gtype == RefStrType)
{
var bytes = Encoding.UTF8.GetBytes(Convert.ToString(value) +
char.MinValue); // Ensure null-terminated string
VipsValue.SetRefString(ref Struct, bytes);
}
else if (fundamental == GObjectType && value is GObject gObject)
{
AddMemoryPressure(gObject.MemoryPressure);
Internal.GValue.SetObject(ref Struct, gObject);
}
else if (gtype == ArrayIntType)
{
if (value is not IEnumerable)
{
value = new[] { value };
}
var integers = value switch
{
int[] ints => ints,
double[] doubles => Array.ConvertAll(doubles, Convert.ToInt32),
object[] objects => Array.ConvertAll(objects, Convert.ToInt32),
_ => throw new ArgumentException(
$"unsupported value type {value.GetType()} for gtype {NetVips.TypeName(gtype)}")
};
VipsValue.SetArrayInt(ref Struct, integers, integers.Length);
}
else if (gtype == ArrayDoubleType)
{
if (value is not IEnumerable)
{
value = new[] { value };
}
var doubles = value switch
{
double[] dbls => dbls,
int[] ints => Array.ConvertAll(ints, Convert.ToDouble),
object[] objects => Array.ConvertAll(objects, Convert.ToDouble),
_ => throw new ArgumentException(
$"unsupported value type {value.GetType()} for gtype {NetVips.TypeName(gtype)}")
};
VipsValue.SetArrayDouble(ref Struct, doubles, doubles.Length);
}
else if (gtype == ArrayImageType && value is Image[] images)
{
var size = images.Length;
VipsValue.SetArrayImage(ref Struct, size);
var ptrArr = VipsValue.GetArrayImage(in Struct, out _);
for (var i = 0; i < size; i++)
{
ref var image = ref images[i];
// the gvalue needs a ref on each of the images
Marshal.WriteIntPtr(ptrArr, i * IntPtr.Size, image.ObjectRef());
AddMemoryPressure(image.MemoryPressure);
}
}
else if (gtype == BlobType && value is VipsBlob blob)
{
AddMemoryPressure((long)blob.Length);
Internal.GValue.SetBoxed(ref Struct, blob);
}
else if (gtype == BlobType)
{
var memory = value switch
{
string strValue => Encoding.UTF8.GetBytes(strValue),
char[] charArrValue => Encoding.UTF8.GetBytes(charArrValue),
byte[] byteArrValue => byteArrValue,
_ => throw new ArgumentException(
$"unsupported value type {value.GetType()} for gtype {NetVips.TypeName(gtype)}")
};
// We need to set the blob to a copy of the string that vips can own
var ptr = GLib.GMalloc((ulong)memory.Length);
Marshal.Copy(memory, 0, ptr, memory.Length);
AddMemoryPressure(memory.Length);
if (NetVips.AtLeastLibvips(8, 6))
{
VipsValue.SetBlobFree(ref Struct, ptr, (ulong)memory.Length);
}
else
{
int FreeFn(nint a, nint b)
{
GLib.GFree(a);
return 0;
}
VipsValue.SetBlob(ref Struct, FreeFn, ptr, (ulong)memory.Length);
}
}
else
{
throw new ArgumentException(
$"unsupported gtype for set {NetVips.TypeName(gtype)}, fundamental {NetVips.TypeName(fundamental)}, value type {value.GetType()}");
}
}
/// <summary>
/// Get the contents of a GValue.
/// </summary>
/// <remarks>
/// The contents of the GValue are read out as a C# type.
/// </remarks>
/// <returns>The contents of this GValue.</returns>
public object Get()
{
var gtype = GetTypeOf();
var fundamental = GType.Fundamental(gtype);
object result;
if (gtype == GBoolType)
{
result = Internal.GValue.GetBoolean(in Struct);
}
else if (gtype == GIntType)
{
result = Internal.GValue.GetInt(in Struct);
}
else if (gtype == GUint64Type)
{
result = Internal.GValue.GetUint64(in Struct);
}
else if (gtype == GDoubleType)
{
result = Internal.GValue.GetDouble(in Struct);
}
else if (fundamental == GEnumType)
{
result = Internal.GValue.GetEnum(in Struct);
}
else if (fundamental == GFlagsType)
{
result = Internal.GValue.GetFlags(in Struct);
}
else if (gtype == GStrType)
{
result = Internal.GValue.GetString(in Struct).ToUtf8String();
}
else if (gtype == RefStrType)
{
result = VipsValue.GetRefString(in Struct, out var size).ToUtf8String(size: (int)size);
}
else if (gtype == ImageType)
{
// g_value_get_object() will not add a ref ... that is
// held by the gvalue
var vi = Internal.GValue.GetObject(in Struct);
// we want a ref that will last with the life of the vimage:
// this ref is matched by the unref that's attached to finalize
// by GObject
var image = new Image(vi);
image.ObjectRef();
result = image;
}
else if (gtype == ArrayIntType)
{
var intPtr = VipsValue.GetArrayInt(in Struct, out var size);
var intArr = new int[size];
Marshal.Copy(intPtr, intArr, 0, size);
result = intArr;
}
else if (gtype == ArrayDoubleType)
{
var intPtr = VipsValue.GetArrayDouble(in Struct, out var size);
var doubleArr = new double[size];
Marshal.Copy(intPtr, doubleArr, 0, size);
result = doubleArr;
}
else if (gtype == ArrayImageType)
{
var ptrArr = VipsValue.GetArrayImage(in Struct, out var size);
var images = new Image[size];
for (var i = 0; i < size; i++)
{
var vi = Marshal.ReadIntPtr(ptrArr, i * IntPtr.Size);
ref var image = ref images[i];
image = new Image(vi);
image.ObjectRef();
}
result = images;
}
else if (gtype == BlobType)
{
var array = VipsValue.GetBlob(in Struct, out var size);
// Blob types are returned as an array of bytes.
var byteArr = new byte[size];
Marshal.Copy(array, byteArr, 0, (int)size);
result = byteArr;
}
else
{
throw new ArgumentException($"unsupported gtype for get {NetVips.TypeName(gtype)}");
}
return result;
}
/// <summary>
/// Get the GType of this GValue.
/// </summary>
/// <returns>The GType of this GValue.</returns>
public nint GetTypeOf()
{
return Struct.GType;
}
/// <summary>
/// Finalizes an instance of the <see cref="GValue"/> class.
/// </summary>
/// <remarks>
/// Allows an object to try to free resources and perform other cleanup
/// operations before it is reclaimed by garbage collection.
/// </remarks>
~GValue()
{
// Do not re-create Dispose clean-up code here.
Dispose(false);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources;
/// <see langword="false"/> to release only unmanaged resources.</param>
protected void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!_disposed)
{
// and tag it to be unset on GC as well
Internal.GValue.Unset(ref Struct);
if (_memoryPressure > 0)
{
GC.RemoveMemoryPressure(_memoryPressure);
_memoryPressure = 0;
}
// Note disposing has been done.
_disposed = true;
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing,
/// or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
GC.SuppressFinalize(this);
}
}

11770
vendor/NetVips/Image.Generated.cs vendored Normal file

File diff suppressed because it is too large Load diff

870
vendor/NetVips/Image.Operators.cs vendored Normal file
View file

@ -0,0 +1,870 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NetVips;
public partial class Image
{
#region auto-generated operator overloads
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(Image left, Image right) =>
left.Call("add", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(double left, Image right) =>
right.Call("linear", 1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(Image left, double right) =>
left.Call("linear", 1.0, right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(double[] left, Image right) =>
right.Call("linear", 1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(Image left, double[] right) =>
left.Call("linear", 1.0, right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(int[] left, Image right) =>
right.Call("linear", 1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> + <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator +(Image left, int[] right) =>
left.Call("linear", 1.0, right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(Image left, Image right) =>
left.Call("subtract", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(double left, Image right) =>
right.Call("linear", -1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(Image left, double right) =>
left.Call("linear", 1.0, -right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(double[] left, Image right) =>
right.Call("linear", -1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(Image left, double[] right) =>
left.Call("linear", 1.0, right.Negate()) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(int[] left, Image right) =>
right.Call("linear", -1.0, left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> - <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator -(Image left, int[] right) =>
left.Call("linear", 1.0, right.Negate()) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(Image left, Image right) =>
left.Call("multiply", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(double left, Image right) =>
right.Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(Image left, double right) =>
left.Call("linear", right, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(double[] left, Image right) =>
right.Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(Image left, double[] right) =>
left.Call("linear", right, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(int[] left, Image right) =>
right.Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> * <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator *(Image left, int[] right) =>
left.Call("linear", right, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(Image left, Image right) =>
left.Call("divide", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(double left, Image right) =>
right.Pow(-1.0).Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(Image left, double right) =>
left.Call("linear", 1.0 / right, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(double[] left, Image right) =>
right.Pow(-1.0).Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(Image left, double[] right) =>
left.Call("linear", right.Invert(), 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(int[] left, Image right) =>
right.Pow(-1.0).Call("linear", left, 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> / <paramref name="right"/>.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator /(Image left, int[] right) =>
left.Call("linear", right.Invert(), 0.0) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(Image left, Image right) =>
left.Call("remainder", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(double left, Image right) =>
right.Call("remainder_const", left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(Image left, double right) =>
left.Call("remainder_const", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(double[] left, Image right) =>
right.Call("remainder_const", left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(Image left, double[] right) =>
left.Call("remainder_const", right) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(int[] left, Image right) =>
right.Call("remainder_const", left) as Image;
/// <summary>
/// This operation calculates <paramref name="left"/> % <paramref name="right"/>
/// (remainder after integer division).
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator %(Image left, int[] right) =>
left.Call("remainder_const", right) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(Image left, Image right) =>
left.Call("boolean", right, Enums.OperationBoolean.And) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(double left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.And, left) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(Image left, double right) =>
left.Call("boolean_const", Enums.OperationBoolean.And, right) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(double[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.And, left) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(Image left, double[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.And, right) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(int[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.And, left) as Image;
/// <summary>
/// This operation computes the logical bitwise AND of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator &(Image left, int[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.And, right) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(Image left, Image right) =>
left.Call("boolean", right, Enums.OperationBoolean.Or) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(double left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Or, left) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(Image left, double right) =>
left.Call("boolean_const", Enums.OperationBoolean.Or, right) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(double[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Or, left) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(Image left, double[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.Or, right) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(int[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Or, left) as Image;
/// <summary>
/// This operation computes the bitwise OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator |(Image left, int[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.Or, right) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(Image left, Image right) =>
left.Call("boolean", right, Enums.OperationBoolean.Eor) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(double left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Eor, left) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(Image left, double right) =>
left.Call("boolean_const", Enums.OperationBoolean.Eor, right) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(double[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Eor, left) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(Image left, double[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.Eor, right) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(int[] left, Image right) =>
right.Call("boolean_const", Enums.OperationBoolean.Eor, left) as Image;
/// <summary>
/// This operation computes the bitwise exclusive-OR of its operands.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ^(Image left, int[] right) =>
left.Call("boolean_const", Enums.OperationBoolean.Eor, right) as Image;
/// <summary>
/// This operation shifts its first operand left by the number of bits specified by its second operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">The number of bits.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <<(Image left, int right) =>
left.Call("boolean_const", Enums.OperationBoolean.Lshift, right) as Image;
/// <summary>
/// This operation shifts its first operand right by the number of bits specified by its second operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">The number of bits.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >>(Image left, int right) =>
left.Call("boolean_const", Enums.OperationBoolean.Rshift, right) as Image;
/// <summary>
/// This operation compares two images on equality.
/// </summary>
/// <param name="left">Left double constant to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ==(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Equal, left) as Image;
/// <summary>
/// This operation compares two images on equality.
/// </summary>
/// <param name="left">Left double array to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ==(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Equal, left) as Image;
/// <summary>
/// This operation compares two images on equality.
/// </summary>
/// <param name="left">Left integer array to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator ==(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Equal, left) as Image;
/// <summary>
/// This operation compares two images on inequality.
/// </summary>
/// <param name="left">Left double constant to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator !=(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Noteq, left) as Image;
/// <summary>
/// This operation compares two images on inequality.
/// </summary>
/// <param name="left">Left double array to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator !=(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Noteq, left) as Image;
/// <summary>
/// This operation compares two images on inequality.
/// </summary>
/// <param name="left">Left integer array to compare.</param>
/// <param name="right">Right <see cref="Image"/> to compare.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator !=(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Noteq, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(Image left, Image right) =>
left.Call("relational", right, Enums.OperationRelational.Less) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.More, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(Image left, double right) =>
left.Call("relational_const", Enums.OperationRelational.Less, right) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.More, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(Image left, double[] right) =>
left.Call("relational_const", Enums.OperationRelational.Less, right) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.More, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <(Image left, int[] right) =>
left.Call("relational_const", Enums.OperationRelational.Less, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(Image left, Image right) =>
left.Call("relational", right, Enums.OperationRelational.More) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Less, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(Image left, double right) =>
left.Call("relational_const", Enums.OperationRelational.More, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Less, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(Image left, double[] right) =>
left.Call("relational_const", Enums.OperationRelational.More, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Less, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >(Image left, int[] right) =>
left.Call("relational_const", Enums.OperationRelational.More, right) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(Image left, Image right) =>
left.Call("relational", right, Enums.OperationRelational.Lesseq) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Moreeq, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(Image left, double right) =>
left.Call("relational_const", Enums.OperationRelational.Lesseq, right) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Moreeq, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(Image left, double[] right) =>
left.Call("relational_const", Enums.OperationRelational.Lesseq, right) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Moreeq, left) as Image;
/// <summary>
/// This operation compares if the left operand is less than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator <=(Image left, int[] right) =>
left.Call("relational_const", Enums.OperationRelational.Lesseq, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(Image left, Image right) =>
left.Call("relational", right, Enums.OperationRelational.Moreeq) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left double constant.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(double left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Lesseq, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double constant.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(Image left, double right) =>
left.Call("relational_const", Enums.OperationRelational.Moreeq, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left double array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(double[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Lesseq, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right double array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(Image left, double[] right) =>
left.Call("relational_const", Enums.OperationRelational.Moreeq, right) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left integer array.</param>
/// <param name="right">Right <see cref="Image"/>.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(int[] left, Image right) =>
right.Call("relational_const", Enums.OperationRelational.Lesseq, left) as Image;
/// <summary>
/// This operation compares if the left operand is greater than or equal to the right operand.
/// </summary>
/// <param name="left">Left <see cref="Image"/>.</param>
/// <param name="right">Right integer array.</param>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image operator >=(Image left, int[] right) =>
left.Call("relational_const", Enums.OperationRelational.Moreeq, right) as Image;
/// <summary>
/// Returns a value indicating whether a given <see cref="Image"/> is definitely <see langword="true"/>.
/// </summary>
/// <param name="image">The image to check.</param>
/// <returns><see langword="true"/> if <paramref name="image"/> is definitely <see langword="true"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator true(Image image) =>
// Always evaluate to false so that each side of the && equation is evaluated
false;
/// <summary>
/// Returns a value indicating whether a given <see cref="Image"/> is definitely <see langword="false"/>.
/// </summary>
/// <param name="image">The image to check.</param>
/// <returns><see langword="true"/> if <paramref name="image"/> is definitely <see langword="false"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator false(Image image) =>
// Always evaluate to false so that each side of the && equation is evaluated
false;
#endregion
}

2328
vendor/NetVips/Image.cs vendored Normal file

File diff suppressed because it is too large Load diff

42
vendor/NetVips/Internal/Enums.cs vendored Normal file
View file

@ -0,0 +1,42 @@
using System;
namespace NetVips.Internal;
internal static class Enums
{
[Flags]
internal enum GParamFlags
{
G_PARAM_READABLE = 1 << 0,
G_PARAM_WRITABLE = 1 << 1,
G_PARAM_READWRITE = G_PARAM_READABLE | G_PARAM_WRITABLE,
G_PARAM_CONSTRUCT = 1 << 2,
G_PARAM_CONSTRUCT_ONLY = 1 << 3,
G_PARAM_LAX_VALIDATION = 1 << 4,
G_PARAM_STATIC_NAME = 1 << 5,
G_PARAM_PRIVATE = G_PARAM_STATIC_NAME,
G_PARAM_STATIC_NICK = 1 << 6,
G_PARAM_STATIC_BLURB = 1 << 7,
G_PARAM_EXPLICIT_NOTIFY = 1 << 30,
G_PARAM_DEPRECATED = 1 << 31
}
[Flags]
internal enum GConnectFlags
{
G_CONNECT_DEFAULT = 0,
G_CONNECT_AFTER = 1 << 0,
G_CONNECT_SWAPPED = 1 << 1
}
[Flags]
internal enum GSignalMatchType
{
G_SIGNAL_MATCH_ID = 1 << 0,
G_SIGNAL_MATCH_DETAIL = 1 << 1,
G_SIGNAL_MATCH_CLOSURE = 1 << 2,
G_SIGNAL_MATCH_FUNC = 1 << 3,
G_SIGNAL_MATCH_DATA = 1 << 4,
G_SIGNAL_MATCH_UNBLOCKED = 1 << 5
}
}

47
vendor/NetVips/Internal/GLib.cs vendored Normal file
View file

@ -0,0 +1,47 @@
using System.Runtime.InteropServices;
using System.Security;
using NetVips.Interop;
using LogLevelFlags = NetVips.Enums.LogLevelFlags;
namespace NetVips.Internal;
internal static class GLib
{
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void LogFuncNative([MarshalAs(UnmanagedType.LPStr)] string logDomain,
LogLevelFlags flags, nint message, nint userData);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_free")]
internal static extern void GFree(nint mem);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_malloc")]
internal static extern nint GMalloc(ulong nBytes);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_log_set_handler")]
internal static extern uint GLogSetHandler([MarshalAs(UnmanagedType.LPStr)] string logDomain,
LogLevelFlags flags, LogFuncNative logFunc, nint userData);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_log_remove_handler")]
internal static extern void
GLogRemoveHandler([MarshalAs(UnmanagedType.LPStr)] string logDomain, uint handlerId);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_log_set_always_fatal")]
internal static extern LogLevelFlags GLogSetAlwaysFatal(LogLevelFlags fatalMask);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GLib, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_log_set_fatal_mask")]
internal static extern LogLevelFlags GLogSetFatalMask(
[MarshalAs(UnmanagedType.LPStr)] string logDomain, LogLevelFlags fatalMask);
}

260
vendor/NetVips/Internal/GObject.cs vendored Normal file
View file

@ -0,0 +1,260 @@
using System.Runtime.InteropServices;
using System.Security;
using NetVips.Interop;
using GObjectManaged = NetVips.GObject;
using VipsBlobManaged = NetVips.VipsBlob;
namespace NetVips.Internal;
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GWeakNotify(nint data, nint objectPointer);
internal static class GObject
{
[StructLayout(LayoutKind.Sequential)]
internal struct Struct
{
internal nint GTypeInstance;
internal uint RefCount;
internal nint QData;
}
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_object_set_property")]
internal static extern void SetProperty(GObjectManaged @object,
[MarshalAs(UnmanagedType.LPStr)] string propertyName, in GValue.Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_object_get_property")]
internal static extern void GetProperty(GObjectManaged @object,
[MarshalAs(UnmanagedType.LPStr)] string propertyName, ref GValue.Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_object_ref")]
internal static extern nint Ref(nint @object);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_object_unref")]
internal static extern void Unref(nint @object);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_object_weak_ref")]
internal static extern void WeakRef(GObjectManaged @object, GWeakNotify notify, nint data);
}
[StructLayout(LayoutKind.Sequential)]
internal struct GEnumValue
{
internal int Value;
[MarshalAs(UnmanagedType.LPStr)]
internal string ValueName;
[MarshalAs(UnmanagedType.LPStr)]
internal string ValueNick;
}
[StructLayout(LayoutKind.Sequential)]
internal struct GEnumClass
{
internal nint GTypeClass;
internal int Minimum;
internal int Maximum;
internal uint NValues;
internal nint Values;
}
internal static class GType
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_type_name")]
internal static extern nint Name(nint type);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_type_from_name")]
internal static extern nint FromName([MarshalAs(UnmanagedType.LPStr)] string name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_type_fundamental")]
internal static extern nint Fundamental(nint typeId);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_type_class_ref")]
internal static extern nint ClassRef(nint type);
}
internal static class GValue
{
[StructLayout(LayoutKind.Explicit, Size = 24)]
internal struct Struct
{
[FieldOffset(0)]
internal nint GType;
[FieldOffset(8)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
internal nint[] Data;
}
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_init")]
internal static extern nint Init(ref Struct value, nint gType);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_unset")]
internal static extern void Unset(ref Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_boolean")]
internal static extern void SetBoolean(ref Struct value, [MarshalAs(UnmanagedType.Bool)] bool vBoolean);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_boolean")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetBoolean(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_int")]
internal static extern void SetInt(ref Struct value, int vInt);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_int")]
internal static extern int GetInt(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_uint64")]
internal static extern void SetUint64(ref Struct value, ulong vUint64);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_uint64")]
internal static extern ulong GetUint64(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_double")]
internal static extern void SetDouble(ref Struct value, double vDouble);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_double")]
internal static extern double GetDouble(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_string")]
internal static extern void SetString(ref Struct value, byte[] vString);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_string")]
internal static extern nint GetString(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_enum")]
internal static extern void SetEnum(ref Struct value, int vEnum);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_enum")]
internal static extern int GetEnum(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_flags")]
internal static extern void SetFlags(ref Struct value, uint vFlags);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_flags")]
internal static extern uint GetFlags(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_object")]
internal static extern void SetObject(ref Struct value, GObjectManaged vObject);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_get_object")]
internal static extern nint GetObject(in Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_value_set_boxed")]
internal static extern void SetBoxed(ref Struct value, VipsBlobManaged boxed);
}
internal static class GParamSpec
{
[StructLayout(LayoutKind.Sequential)]
internal struct Struct
{
internal nint GTypeInstance;
internal nint Name;
internal Enums.GParamFlags Flags;
internal nint ValueType;
internal nint OwnerType;
internal nint Nick;
internal nint Blurb;
internal nint QData;
internal uint RefCount;
internal uint ParamId;
}
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_param_spec_get_blurb")]
internal static extern nint GetBlurb(in Struct pspec);
}
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GClosureNotify(nint data, nint closure);
internal static class GSignal
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_signal_connect_data")]
internal static extern ulong ConnectData(GObjectManaged instance,
[MarshalAs(UnmanagedType.LPStr)] string detailedSignal,
nint cHandler, nint data,
GClosureNotify destroyData, Enums.GConnectFlags connectFlags);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_signal_handler_disconnect")]
internal static extern void HandlerDisconnect(GObjectManaged instance, ulong handlerId);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "g_signal_handlers_disconnect_matched")]
internal static extern uint HandlersDisconnectMatched(GObjectManaged instance,
Enums.GSignalMatchType mask, uint signalId, uint detail, nint closure,
nint func, nint data);
}

708
vendor/NetVips/Internal/Vips.cs vendored Normal file
View file

@ -0,0 +1,708 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using NetVips.Interop;
using ArgumentFlags = NetVips.Enums.ArgumentFlags;
using BandFormat = NetVips.Enums.BandFormat;
using OperationFlags = NetVips.Enums.OperationFlags;
using VipsBlobManaged = NetVips.VipsBlob;
using VipsObjectManaged = NetVips.VipsObject;
namespace NetVips.Internal;
internal static class Vips
{
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate nint TypeMap2Fn(nint type, nint a, nint b);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate nint ArgumentMapFn(nint @object, nint pspec, nint argumentClass,
nint argumentInstance, nint a, nint b);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int CallbackFn(nint a, nint b);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_init")]
internal static extern int Init([MarshalAs(UnmanagedType.LPStr)] string argv0);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_shutdown")]
internal static extern void Shutdown();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_leak_set")]
internal static extern void LeakSet([MarshalAs(UnmanagedType.Bool)] bool leak);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_profile_set")]
internal static extern void ProfileSet([MarshalAs(UnmanagedType.Bool)] bool profile);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_get_max")]
internal static extern int CacheGetMax();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_set_max")]
internal static extern void CacheSetMax(int max);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_get_max_mem")]
internal static extern nuint CacheGetMaxMem();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_set_max_mem")]
internal static extern void CacheSetMaxMem(ulong maxMem);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_get_max_files")]
internal static extern int CacheGetMaxFiles();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_set_max_files")]
internal static extern void CacheSetMaxFiles(int maxFiles);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_get_size")]
internal static extern int CacheGetSize();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_set_trace")]
internal static extern void CacheSetTrace([MarshalAs(UnmanagedType.Bool)] bool trace);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_concurrency_set")]
internal static extern void ConcurrencySet(int concurrency);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_concurrency_get")]
internal static extern int ConcurrencyGet();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_vector_isenabled")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool VectorIsEnabled();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_vector_set_enabled")]
internal static extern void VectorSet([MarshalAs(UnmanagedType.Bool)] bool enabled);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_block_untrusted_set")]
internal static extern void BlockUntrustedSet([MarshalAs(UnmanagedType.Bool)] bool state);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_tracked_get_allocs")]
internal static extern int TrackedGetAllocs();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_tracked_get_mem")]
internal static extern int TrackedGetMem();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_tracked_get_files")]
internal static extern int TrackedGetFiles();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_tracked_get_mem_highwater")]
internal static extern ulong TrackedGetMemHighwater();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_version")]
internal static extern int Version(int flag);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_error_buffer")]
internal static extern nint ErrorBuffer();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_error_clear")]
internal static extern void ErrorClear();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_error_freeze")]
internal static extern void ErrorFreeze();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_error_thaw")]
internal static extern void ErrorThaw();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_path_filename7")]
internal static extern nint PathFilename7(byte[] path);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_path_mode7")]
internal static extern nint PathMode7(byte[] path);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_filename_get_filename")]
internal static extern nint GetFilename(byte[] vipsFilename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_filename_get_options")]
internal static extern nint GetOptions(byte[] vipsFilename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_blend_mode_get_type")]
internal static extern nint BlendModeGetType();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_interpretation_get_type")]
internal static extern nint InterpretationGetType();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_band_format_get_type")]
internal static extern nint BandFormatGetType();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_argument_map")]
internal static extern nint ArgumentMap(VipsObjectManaged @object, ArgumentMapFn fn, nint a,
nint b);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_type_map")]
internal static extern nint TypeMap(nint @base, TypeMap2Fn fn, nint a, nint b);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_type_find")]
internal static extern nint TypeFind([MarshalAs(UnmanagedType.LPStr)] string basename,
[MarshalAs(UnmanagedType.LPStr)] string nickname);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_nickname_find")]
internal static extern nint NicknameFind(nint type);
internal static string PathFilename7(string path)
{
var bytes = Encoding.UTF8.GetBytes(path + char.MinValue); // Ensure null-terminated string
return PathFilename7(bytes).ToUtf8String();
}
internal static string PathMode7(string path)
{
var bytes = Encoding.UTF8.GetBytes(path + char.MinValue); // Ensure null-terminated string
return PathMode7(bytes).ToUtf8String();
}
}
internal static class VipsObject
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_object_get_args")]
internal static extern int GetArgs(VipsObjectManaged @object, out nint names, out nint flags,
out int nArgs);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_object_get_argument")]
internal static extern int GetArgument(VipsObjectManaged @object,
[MarshalAs(UnmanagedType.LPStr)] string name,
out nint pspec, out VipsArgumentClass argumentClass,
out VipsArgumentInstance argumentInstance);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_object_set_from_string")]
internal static extern int SetFromString(VipsObjectManaged @object,
[MarshalAs(UnmanagedType.LPStr)] string @string);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_object_print_all")]
internal static extern void PrintAll();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_object_unref_outputs")]
internal static extern void UnrefOutputs(VipsObjectManaged @object);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_object_get_description")]
internal static extern nint GetDescription(VipsObjectManaged @object);
}
[StructLayout(LayoutKind.Sequential)]
internal struct VipsArgumentClass
{
internal nint Parent;
internal nint ObjectClass;
internal ArgumentFlags Flags;
internal int Priority;
internal uint Offset;
}
[StructLayout(LayoutKind.Sequential)]
internal struct VipsArgumentInstance
{
internal nint Parent;
internal nint ArgumentClass;
internal nint Object;
[MarshalAs(UnmanagedType.Bool)]
internal bool Assigned;
internal uint CloseId;
internal uint InvalidateId;
}
internal static class VipsBlob
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_blob_get")]
internal static extern nint Get(VipsBlobManaged blob, out nuint length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_blob_copy")]
internal static extern unsafe nint Copy(void* data, nuint length);
}
internal static class VipsArea
{
[StructLayout(LayoutKind.Sequential)]
internal struct Struct
{
internal nint Data;
internal nuint Length;
internal int N;
// private
internal int Count;
internal nint Lock;
internal Vips.CallbackFn FreeFn;
internal nint Client;
internal nint Type;
internal nuint SizeofType;
}
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_area_unref")]
internal static extern nint Unref(nint blob);
}
internal static class VipsValue
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_get_ref_string")]
internal static extern nint GetRefString(in GValue.Struct value, out ulong length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_ref_string")]
internal static extern void SetRefString(ref GValue.Struct value, byte[] str);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_get_blob")]
internal static extern nint GetBlob(in GValue.Struct value, out ulong length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_blob")]
internal static extern void SetBlob(ref GValue.Struct value, Vips.CallbackFn freeFn,
nint data, ulong length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_blob_free")]
internal static extern void SetBlobFree(ref GValue.Struct value, nint data,
ulong length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_get_array_double")]
internal static extern nint GetArrayDouble(in GValue.Struct value, out int n);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_array_double")]
internal static extern void SetArrayDouble(ref GValue.Struct value,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
double[] array, int n);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_get_array_int")]
internal static extern nint GetArrayInt(in GValue.Struct value, out int n);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_array_int")]
internal static extern void SetArrayInt(ref GValue.Struct value,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
int[] array, int n);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_get_array_image")]
internal static extern nint GetArrayImage(in GValue.Struct value, out int n);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_value_set_array_image")]
internal static extern void SetArrayImage(ref GValue.Struct value, int n);
}
internal static class VipsImage
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_get_page_height")]
internal static extern int GetPageHeight(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_invalidate_all")]
internal static extern void InvalidateAll(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_set_progress")]
internal static extern void SetProgress(Image image, [MarshalAs(UnmanagedType.Bool)] bool progress);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_iskilled")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool IsKilled(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_set_kill")]
internal static extern void SetKill(Image image, [MarshalAs(UnmanagedType.Bool)] bool kill);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_from_memory")]
internal static extern nint NewFromMemory(nint data, nuint 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 nint NewFromMemory(void* data, nuint size, int width, int height,
int bands, BandFormat format);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_from_memory_copy")]
internal static extern nint NewFromMemoryCopy(nint data, nuint size, int width, int height,
int bands, BandFormat format);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_from_memory_copy")]
internal static extern unsafe nint NewFromMemoryCopy(void* data, nuint size, int width, int height,
int bands, BandFormat format);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_matrix_from_array")]
internal static extern nint NewMatrixFromArray(int width, int height, double[] array, int size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_new_temp_file")]
internal static extern nint NewTempFile(byte[] format);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_write")]
internal static extern int Write(Image image, Image @out);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_write_to_memory")]
internal static extern nint WriteToMemory(Image @in, out ulong size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_hasalpha")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool HasAlpha(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_addalpha")]
internal static extern int AddAlpha(Image image, out nint @out, nint sentinel = default);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_copy_memory")]
internal static extern nint CopyMemory(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_image_set")]
internal static extern void Set(Image image, [MarshalAs(UnmanagedType.LPStr)] string name,
in GValue.Struct value);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_image_get")]
internal static extern int Get(Image image, [MarshalAs(UnmanagedType.LPStr)] string name,
out GValue.Struct valueCopy);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_get_typeof")]
internal static extern nint GetTypeof(Image image, [MarshalAs(UnmanagedType.LPStr)] string name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_remove")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool Remove(Image image, [MarshalAs(UnmanagedType.LPStr)] string name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_image_get_fields")]
internal static extern nint GetFields(Image image);
}
internal static class VipsInterpolate
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_interpolate_new")]
internal static extern nint New([MarshalAs(UnmanagedType.LPStr)] string nickname);
}
internal static class VipsRegion
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_region_new")]
internal static extern nint New(Image image);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_region_fetch")]
internal static extern nint Fetch(Region region, int left, int top, int width, int height, out ulong length);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_region_width")]
internal static extern int Width(Region region);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_region_height")]
internal static extern int Height(Region region);
}
internal static class VipsOperation
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_operation_get_flags")]
internal static extern OperationFlags GetFlags(Operation operation);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_operation_new")]
internal static extern nint New([MarshalAs(UnmanagedType.LPStr)] string name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_cache_operation_build")]
internal static extern nint Build(Operation operation);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_operation_flags_get_type")]
internal static extern nint FlagsGetType();
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_operation_block_set")]
internal static extern void BlockSet([MarshalAs(UnmanagedType.LPStr)] string name,
[MarshalAs(UnmanagedType.Bool)] bool state);
}
internal static class VipsForeign
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load")]
internal static extern nint FindLoad(nint filename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load")]
internal static extern nint FindLoad(byte[] filename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load_buffer")]
internal static extern nint FindLoadBuffer(byte[] data, ulong size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load_buffer")]
internal static extern nint FindLoadBuffer(nint data, ulong size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load_buffer")]
internal static extern unsafe nint FindLoadBuffer(void* data, ulong size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_load_source")]
internal static extern nint FindLoadSource(Source stream);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_save")]
internal static extern nint FindSave(nint filename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_save_buffer")]
internal static extern nint FindSaveBuffer(byte[] name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_find_save_target")]
internal static extern nint FindSaveTarget(byte[] name);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_foreign_get_suffixes")]
internal static extern nint GetSuffixes();
}
internal static class VipsConnection
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_connection_filename")]
internal static extern nint FileName(Connection connection);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_connection_nick")]
internal static extern nint Nick(Connection connection);
}
internal static class VipsSource
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_new_from_descriptor")]
internal static extern nint NewFromDescriptor(int descriptor);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_new_from_file")]
internal static extern nint NewFromFile(byte[] filename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_new_from_blob")]
internal static extern nint NewFromBlob(VipsBlobManaged blob);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_new_from_memory")]
internal static extern nint NewFromMemory(nint data, nuint size);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl, EntryPoint = "vips_source_map_blob")]
internal static extern nint MapBlob(Source source);
}
internal static class VipsSourceCustom
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_source_custom_new")]
internal static extern nint New();
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long ReadSignal(nint sourcePtr, nint buffer, long length, nint userDataPtr);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long SeekSignal(nint sourcePtr, long offset, int whence, nint userDataPtr);
}
internal static class VipsTarget
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_target_new_to_descriptor")]
internal static extern nint NewToDescriptor(int descriptor);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_target_new_to_file")]
internal static extern nint NewToFile(byte[] filename);
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_target_new_to_memory")]
internal static extern nint NewToMemory();
}
internal static class VipsTargetCustom
{
[SuppressUnmanagedCodeSecurity]
[DllImport(Libraries.Vips, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "vips_target_custom_new")]
internal static extern nint New();
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long WriteSignal(nint targetPtr,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
byte[] buffer, int length, nint userDataPtr);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long ReadSignal(nint targetPtr, nint buffer, long length, nint userDataPtr);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long SeekSignal(nint targetPtr, long offset, int whence, nint userDataPtr);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int EndSignal(nint targetPtr, nint userDataPtr);
}

12
vendor/NetVips/Interop/Libraries.cs vendored Normal file
View file

@ -0,0 +1,12 @@
namespace NetVips.Interop;
internal static class Libraries
{
/// <remarks>
/// These library names are remapped in a cross-platform manner,
/// <see cref="ModuleInitializer.Initialize"/>.
/// </remarks>
internal const string GLib = "libglib-2.0-0.dll",
GObject = "libgobject-2.0-0.dll",
Vips = "libvips-42.dll";
}

43
vendor/NetVips/Interpolate.cs vendored Normal file
View file

@ -0,0 +1,43 @@
using System;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Make interpolators for operators like <see cref="Image.Affine"/>.
/// </summary>
public class Interpolate : VipsObject
{
private Interpolate(nint pointer) : base(pointer)
{
}
/// <summary>
/// Make a new interpolator by name.
/// </summary>
/// <remarks>
/// Make a new interpolator from the libvips class nickname. For example:
/// <code language="lang-csharp">
/// var inter = Interpolate.NewFromName("bicubic");
/// </code>
/// You can get a list of all supported interpolators from the command-line
/// with:
/// <code language="lang-shell">
/// $ vips -l interpolate
/// </code>
/// See for example <see cref="Image.Affine"/>.
/// </remarks>
/// <param name="name">libvips class nickname.</param>
/// <returns>A new <see cref="Interpolate"/>.</returns>
/// <exception cref="VipsException">If unable to make a new interpolator from <paramref name="name"/>.</exception>
public static Interpolate NewFromName(string name)
{
var vi = VipsInterpolate.New(name);
if (vi == IntPtr.Zero)
{
throw new VipsException($"no such interpolator {name}");
}
return new Interpolate(vi);
}
}

219
vendor/NetVips/Introspect.cs vendored Normal file
View file

@ -0,0 +1,219 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Build introspection data for operations.
/// </summary>
/// <remarks>
/// Make an operation, introspect it, and build a structure representing
/// everything we know about it.
/// </remarks>
public class Introspect
{
/// <summary>
/// A cache for introspection data.
/// </summary>
private static readonly ConcurrentDictionary<string, Introspect> IntrospectCache = new();
/// <summary>
/// An object structure that encapsulates the metadata
/// required to specify arguments.
/// </summary>
public struct Argument
{
/// <summary>
/// Name of this argument.
/// </summary>
public string Name;
/// <summary>
/// Flags for this argument.
/// </summary>
public Enums.ArgumentFlags Flags;
/// <summary>
/// The GType for this argument.
/// </summary>
public nint Type;
}
/// <summary>
/// The first required input image or <see langword="null"/>.
/// </summary>
public Argument? MemberX;
/// <summary>
/// A bool indicating if this operation is mutable.
/// </summary>
public readonly bool Mutable;
/// <summary>
/// The required input for this operation.
/// </summary>
public readonly List<Argument> RequiredInput = new();
/// <summary>
/// The optional input for this operation.
/// </summary>
public readonly Dictionary<string, Argument> OptionalInput = new();
/// <summary>
/// The required output for this operation.
/// </summary>
public readonly List<Argument> RequiredOutput = new();
/// <summary>
/// The optional output for this operation.
/// </summary>
public readonly Dictionary<string, Argument> OptionalOutput = new();
/// <summary>
/// Build introspection data for a specified operation name.
/// </summary>
/// <param name="operationName">The operation name to introspect.</param>
private Introspect(string operationName)
{
using var op = Operation.NewFromName(operationName);
var arguments = GetArgs(op);
foreach (var entry in arguments)
{
var name = entry.Key;
var flag = entry.Value;
var gtype = op.GetTypeOf(name);
var details = new Argument
{
Name = name,
Flags = flag,
Type = gtype
};
if ((flag & Enums.ArgumentFlags.INPUT) != 0)
{
if ((flag & Enums.ArgumentFlags.REQUIRED) != 0 &&
(flag & Enums.ArgumentFlags.DEPRECATED) == 0)
{
// the first required input image arg will be self
if (!MemberX.HasValue && gtype == GValue.ImageType)
{
MemberX = details;
}
else
{
RequiredInput.Add(details);
}
}
else
{
// we allow deprecated optional args
OptionalInput[name] = details;
}
// modified input arguments count as mutable.
if ((flag & Enums.ArgumentFlags.MODIFY) != 0 &&
(flag & Enums.ArgumentFlags.REQUIRED) != 0 &&
(flag & Enums.ArgumentFlags.DEPRECATED) == 0)
{
Mutable = true;
}
}
else if ((flag & Enums.ArgumentFlags.OUTPUT) != 0)
{
if ((flag & Enums.ArgumentFlags.REQUIRED) != 0 &&
(flag & Enums.ArgumentFlags.DEPRECATED) == 0)
{
RequiredOutput.Add(details);
}
else
{
// again, allow deprecated optional args
OptionalOutput[name] = details;
}
}
}
}
/// <summary>
/// Get all arguments for an operation.
/// </summary>
/// <remarks>
/// Not quick! Try to call this infrequently.
/// </remarks>
/// <param name="operation">Operation to lookup.</param>
/// <returns>Arguments for the operation.</returns>
private IEnumerable<KeyValuePair<string, Enums.ArgumentFlags>> GetArgs(Operation operation)
{
var args = new List<KeyValuePair<string, Enums.ArgumentFlags>>();
void AddArg(string name, Enums.ArgumentFlags flags)
{
// libvips uses '-' to separate parts of arg names, but we
// need '_' for C#
name = name.Replace("-", "_");
args.Add(new KeyValuePair<string, Enums.ArgumentFlags>(name, flags));
}
// vips_object_get_args was added in 8.7
if (NetVips.AtLeastLibvips(8, 7))
{
var result = Internal.VipsObject.GetArgs(operation, out var names, out var flags, out var nArgs);
if (result != 0)
{
throw new VipsException("unable to get arguments from operation");
}
for (var i = 0; i < nArgs; i++)
{
var flag = (Enums.ArgumentFlags)Marshal.PtrToStructure<int>(flags + i * sizeof(int));
if ((flag & Enums.ArgumentFlags.CONSTRUCT) == 0)
{
continue;
}
var name = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(names, i * IntPtr.Size));
AddArg(name, flag);
}
}
else
{
nint AddConstruct(nint self, nint pspec, nint argumentClass, nint argumentInstance,
nint a, nint b)
{
var flags = Marshal.PtrToStructure<VipsArgumentClass>(argumentClass).Flags;
if ((flags & Enums.ArgumentFlags.CONSTRUCT) == 0)
{
return IntPtr.Zero;
}
var name = Marshal.PtrToStringAnsi(Marshal.PtrToStructure<GParamSpec.Struct>(pspec).Name);
AddArg(name, flags);
return IntPtr.Zero;
}
Vips.ArgumentMap(operation, AddConstruct, IntPtr.Zero, IntPtr.Zero);
}
return args;
}
/// <summary>
/// Get introspection data for a specified operation name.
/// </summary>
/// <param name="operationName">Operation name.</param>
/// <returns>Introspection data.</returns>
public static Introspect Get(string operationName)
{
return IntrospectCache.GetOrAdd(operationName, name => new Introspect(name));
}
}

21
vendor/NetVips/LICENSE vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-present Kleis Auke Wolthuizen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

137
vendor/NetVips/Log.cs vendored Normal file
View file

@ -0,0 +1,137 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Wrapper for message logging functions.
/// </summary>
public static class Log
{
private static GLib.LogFuncNative _nativeHandler;
/// <summary>
/// Specifies the prototype of log handler functions.
/// </summary>
/// <param name="logDomain">The log domain of the message.</param>
/// <param name="logLevel">The log level of the message (including the fatal and recursion flags).</param>
/// <param name="message">The message to process.</param>
public delegate void LogDelegate(string logDomain, Enums.LogLevelFlags logLevel, string message);
private static void NativeCallback(string logDomain, Enums.LogLevelFlags flags, nint messagePtr,
nint userData)
{
if (userData == IntPtr.Zero)
{
return;
}
var message = messagePtr.ToUtf8String();
var gch = (GCHandle)userData;
if (gch.Target is LogDelegate func)
{
func(logDomain, flags, message);
}
}
private static readonly ConcurrentDictionary<uint, GCHandle> Handlers = new();
/// <summary>
/// Sets the log handler for a domain and a set of log levels.
/// </summary>
/// <param name="logDomain">The log domain, or <see langword="null"/> for the default "" application domain.</param>
/// <param name="flags">The log levels to apply the log handler for.</param>
/// <param name="logFunc">The log handler function.</param>
/// <returns>The id of the handler.</returns>
public static uint SetLogHandler(string logDomain, Enums.LogLevelFlags flags, LogDelegate logFunc)
{
_nativeHandler ??= NativeCallback;
var gch = GCHandle.Alloc(logFunc);
var result = GLib.GLogSetHandler(logDomain, flags, _nativeHandler, (nint)gch);
Handlers.AddOrUpdate(result, gch, (_, _) => gch);
return result;
}
/// <summary>
/// Removes the log handler.
/// </summary>
/// <param name="logDomain">The log domain.</param>
/// <param name="handlerId">The id of the handler, which was returned in <see cref="SetLogHandler"/>.</param>
public static void RemoveLogHandler(string logDomain, uint handlerId)
{
if (Handlers != null &&
Handlers.ContainsKey(handlerId) &&
Handlers.TryRemove(handlerId, out var handler))
{
handler.Free();
}
GLib.GLogRemoveHandler(logDomain, handlerId);
}
/// <summary>
/// Sets the message levels which are always fatal, in any log domain.
/// When a message with any of these levels is logged the program terminates.
/// </summary>
/// <param name="fatalMask">The mask containing bits set for each level of error which is to be fatal.</param>
/// <returns>The old fatal mask.</returns>
public static Enums.LogLevelFlags SetAlwaysFatal(Enums.LogLevelFlags fatalMask)
{
return GLib.GLogSetAlwaysFatal(fatalMask);
}
/// <summary>
/// Sets the log levels which are fatal in the given domain.
/// </summary>
/// <param name="logDomain">The log domain.</param>
/// <param name="fatalMask">The new fatal mask.</param>
/// <returns>The old fatal mask for the log domain.</returns>
public static Enums.LogLevelFlags SetAlwaysFatal(string logDomain, Enums.LogLevelFlags fatalMask)
{
return GLib.GLogSetFatalMask(logDomain, fatalMask);
}
/// <summary>
/// Common logging method.
/// </summary>
/// <remarks>
/// Sample usage:
/// <code language="lang-csharp">
/// // Print the messages for the NULL domain
/// var logFunc = new LogFunc(Log.PrintLogFunction);
/// Log.SetLogHandler(null, Enums.LogLevelFlags.All, logFunc);
/// </code>
/// </remarks>
/// <param name="domain">The log domain of the message.</param>
/// <param name="level">The log level of the message (including the fatal and recursion flags).</param>
/// <param name="message">The message to process.</param>
public static void PrintLogFunction(string domain, Enums.LogLevelFlags level, string message)
{
Console.WriteLine("Domain: '{0}' Level: {1}", domain, level);
Console.WriteLine("Message: {0}", message);
}
/// <summary>
/// Common logging method.
/// </summary>
/// <remarks>
/// Sample usage:
/// <code language="lang-csharp">
/// // Print messages and stack trace for vips critical messages
/// var logFunc = new LogFunc(Log.PrintTraceLogFunction);
/// Log.SetLogHandler("VIPS", Enums.LogLevelFlags.Critical, logFunc);
/// </code>
/// </remarks>
/// <param name="domain">The log domain of the message.</param>
/// <param name="level">The log level of the message (including the fatal and recursion flags).</param>
/// <param name="message">The message to process.</param>
public static void PrintTraceLogFunction(string domain, Enums.LogLevelFlags level, string message)
{
PrintLogFunction(domain, level, message);
Console.WriteLine("Trace follows:\n{0}", new StackTrace());
}
}

139
vendor/NetVips/ModuleInitializer.cs vendored Normal file
View file

@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using NetVips.Interop;
namespace NetVips;
/// <summary>
/// All code inside the <see cref="Initialize"/> method is ran as soon as the assembly is loaded.
/// </summary>
public static class ModuleInitializer
{
/// <summary>
/// Is vips initialized?
/// </summary>
public static bool VipsInitialized;
/// <summary>
/// Contains the exception when initialization of libvips fails.
/// </summary>
public static Exception Exception;
/// <summary>
/// Could contain the version number of libvips in an 3-bytes integer.
/// </summary>
public static int? Version;
#if NET6_0_OR_GREATER
/// <summary>
/// Windows specific: is GLib statically-linked in `libvips-42.dll`?
/// </summary>
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
private static bool _gLibStaticallyLinked = true;
/// <summary>
/// A cache for <see cref="DllImportResolver"/>.
/// </summary>
internal static readonly Dictionary<string, nint> DllImportCache = new();
internal static string RemapLibraryName(string libraryName)
{
// For Windows, we try to locate the GLib symbols within
// `libvips-42.dll` first. If these symbols cannot be found there,
// we proceed to locate them within `libglib-2.0-0.dll` and
// `libgobject-2.0-0.dll`. Note that this is only possible when
// targeting .NET 6 or higher. As a result, we always ship at least
// 3 DLLs in a separate package for .NET Framework.
if (OperatingSystem.IsWindows())
{
return _gLibStaticallyLinked ? Libraries.Vips : libraryName;
}
// FIXME: Switch to `OperatingSystem.IsApplePlatform()` once public.
// See: https://github.com/dotnet/runtime/issues/113262
var isApplePlatform = OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() ||
OperatingSystem.IsTvOS() || OperatingSystem.IsWatchOS();
// We can safely remap the library names to `libvips.so.42` on *nix
// and `libvips.42.dylib` on macOS since DLLImport uses dlsym() there.
// This function also searches for named symbols in the dependencies
// of the shared library. Therefore, we can provide libvips as a
// single shared library with all dependencies statically linked
// without breaking compatibility with the shared builds
// (i.e. what is usually installed via package managers).
return isApplePlatform ? "libvips.42.dylib" : "libvips.so.42";
}
internal static nint DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
libraryName = RemapLibraryName(libraryName);
if (DllImportCache.TryGetValue(libraryName, out var cachedHandle))
{
return cachedHandle;
}
var handle = NativeLibrary.Load(libraryName, assembly, searchPath);
DllImportCache[libraryName] = handle;
return handle;
}
#endif
/// <summary>
/// Initializes the module.
/// </summary>
#pragma warning disable CA2255
[System.Runtime.CompilerServices.ModuleInitializer]
#pragma warning restore CA2255
public static void Initialize()
{
#if NET6_0_OR_GREATER
try
{
NativeLibrary.SetDllImportResolver(typeof(ModuleInitializer).Assembly, DllImportResolver);
}
catch
{
// Ignored; allows this function to be called multiple times.
}
#endif
try
{
VipsInitialized = NetVips.Init();
if (VipsInitialized)
{
Version = NetVips.Version(0, false);
Version = (Version << 8) + NetVips.Version(1, false);
Version = (Version << 8) + NetVips.Version(2, false);
#if NET6_0_OR_GREATER
if (!OperatingSystem.IsWindows())
{
return;
}
try
{
_gLibStaticallyLinked = NetVips.TypeFromName("VipsImage") != IntPtr.Zero;
}
catch
{
_gLibStaticallyLinked = false;
}
#endif
}
else
{
Exception = new VipsException("unable to initialize libvips");
}
}
catch (Exception e)
{
VipsInitialized = false;
Exception = e;
}
}
}

View file

@ -0,0 +1,11 @@
// This file enables ModuleInitializer, a C# 9 feature to work with .NET Framework.
#if NETFRAMEWORK
namespace System.Runtime.CompilerServices;
/// <inheritdoc />
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class ModuleInitializerAttribute : Attribute
{
}
#endif

293
vendor/NetVips/MutableImage.Generated.cs vendored Normal file
View file

@ -0,0 +1,293 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// libvips version: 8.17.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NetVips;
public sealed partial class MutableImage
{
#region auto-generated functions
/// <summary>
/// Draw a circle on an image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawCircle(ink, cx, cy, radius, fill: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="cx">Centre of draw_circle.</param>
/// <param name="cy">Centre of draw_circle.</param>
/// <param name="radius">Radius in pixels.</param>
/// <param name="fill">Draw a solid object.</param>
public void DrawCircle(double[] ink, int cx, int cy, int radius, bool? fill = null)
{
var options = new VOption();
options.AddIfPresent(nameof(fill), fill);
this.Call("draw_circle", options, ink, cx, cy, radius);
}
/// <summary>
/// Flood-fill an area.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawFlood(ink, x, y, test: Image, equal: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x">DrawFlood start point.</param>
/// <param name="y">DrawFlood start point.</param>
/// <param name="test">Test pixels in this image.</param>
/// <param name="equal">DrawFlood while equal to edge.</param>
public void DrawFlood(double[] ink, int x, int y, Image test = null, bool? equal = null)
{
var options = new VOption();
options.AddIfPresent(nameof(test), test);
options.AddIfPresent(nameof(equal), equal);
this.Call("draw_flood", options, ink, x, y);
}
/// <summary>
/// Flood-fill an area.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawFlood(ink, x, y, out var left, test: Image, equal: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x">DrawFlood start point.</param>
/// <param name="y">DrawFlood start point.</param>
/// <param name="left">Left edge of modified area.</param>
/// <param name="test">Test pixels in this image.</param>
/// <param name="equal">DrawFlood while equal to edge.</param>
public void DrawFlood(double[] ink, int x, int y, out int left, Image test = null, bool? equal = null)
{
var options = new VOption();
options.AddIfPresent(nameof(test), test);
options.AddIfPresent(nameof(equal), equal);
options.Add("left", true);
var results = this.Call("draw_flood", options, ink, x, y) as object[];
var opts = results?[1] as VOption;
left = opts?["left"] is int out1 ? out1 : 0;
}
/// <summary>
/// Flood-fill an area.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawFlood(ink, x, y, out var left, out var top, test: Image, equal: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x">DrawFlood start point.</param>
/// <param name="y">DrawFlood start point.</param>
/// <param name="left">Left edge of modified area.</param>
/// <param name="top">Top edge of modified area.</param>
/// <param name="test">Test pixels in this image.</param>
/// <param name="equal">DrawFlood while equal to edge.</param>
public void DrawFlood(double[] ink, int x, int y, out int left, out int top, Image test = null, bool? equal = null)
{
var options = new VOption();
options.AddIfPresent(nameof(test), test);
options.AddIfPresent(nameof(equal), equal);
options.Add("left", true);
options.Add("top", true);
var results = this.Call("draw_flood", options, ink, x, y) as object[];
var opts = results?[1] as VOption;
left = opts?["left"] is int out1 ? out1 : 0;
top = opts?["top"] is int out2 ? out2 : 0;
}
/// <summary>
/// Flood-fill an area.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawFlood(ink, x, y, out var left, out var top, out var width, test: Image, equal: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x">DrawFlood start point.</param>
/// <param name="y">DrawFlood start point.</param>
/// <param name="left">Left edge of modified area.</param>
/// <param name="top">Top edge of modified area.</param>
/// <param name="width">Width of modified area.</param>
/// <param name="test">Test pixels in this image.</param>
/// <param name="equal">DrawFlood while equal to edge.</param>
public void DrawFlood(double[] ink, int x, int y, out int left, out int top, out int width, Image test = null, bool? equal = null)
{
var options = new VOption();
options.AddIfPresent(nameof(test), test);
options.AddIfPresent(nameof(equal), equal);
options.Add("left", true);
options.Add("top", true);
options.Add("width", true);
var results = this.Call("draw_flood", options, ink, x, y) as object[];
var opts = results?[1] as VOption;
left = opts?["left"] is int out1 ? out1 : 0;
top = opts?["top"] is int out2 ? out2 : 0;
width = opts?["width"] is int out3 ? out3 : 0;
}
/// <summary>
/// Flood-fill an area.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawFlood(ink, x, y, out var left, out var top, out var width, out var height, test: Image, equal: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x">DrawFlood start point.</param>
/// <param name="y">DrawFlood start point.</param>
/// <param name="left">Left edge of modified area.</param>
/// <param name="top">Top edge of modified area.</param>
/// <param name="width">Width of modified area.</param>
/// <param name="height">Height of modified area.</param>
/// <param name="test">Test pixels in this image.</param>
/// <param name="equal">DrawFlood while equal to edge.</param>
public void DrawFlood(double[] ink, int x, int y, out int left, out int top, out int width, out int height, Image test = null, bool? equal = null)
{
var options = new VOption();
options.AddIfPresent(nameof(test), test);
options.AddIfPresent(nameof(equal), equal);
options.Add("left", true);
options.Add("top", true);
options.Add("width", true);
options.Add("height", true);
var results = this.Call("draw_flood", options, ink, x, y) as object[];
var opts = results?[1] as VOption;
left = opts?["left"] is int out1 ? out1 : 0;
top = opts?["top"] is int out2 ? out2 : 0;
width = opts?["width"] is int out3 ? out3 : 0;
height = opts?["height"] is int out4 ? out4 : 0;
}
/// <summary>
/// Paint an image into another image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawImage(sub, x, y, mode: Enums.CombineMode));
/// </code>
/// </example>
/// <param name="sub">Sub-image to insert into main image.</param>
/// <param name="x">Draw image here.</param>
/// <param name="y">Draw image here.</param>
/// <param name="mode">Combining mode.</param>
public void DrawImage(Image sub, int x, int y, Enums.CombineMode? mode = null)
{
var options = new VOption();
options.AddIfPresent(nameof(mode), mode);
this.Call("draw_image", options, sub, x, y);
}
/// <summary>
/// Draw a line on an image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawLine(ink, x1, y1, x2, y2));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="x1">Start of draw_line.</param>
/// <param name="y1">Start of draw_line.</param>
/// <param name="x2">End of draw_line.</param>
/// <param name="y2">End of draw_line.</param>
public void DrawLine(double[] ink, int x1, int y1, int x2, int y2)
{
this.Call("draw_line", ink, x1, y1, x2, y2);
}
/// <summary>
/// Draw a mask on an image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawMask(ink, mask, x, y));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="mask">Mask of pixels to draw.</param>
/// <param name="x">Draw mask here.</param>
/// <param name="y">Draw mask here.</param>
public void DrawMask(double[] ink, Image mask, int x, int y)
{
this.Call("draw_mask", ink, mask, x, y);
}
/// <summary>
/// Paint a rectangle on an image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawRect(ink, left, top, width, height, fill: bool));
/// </code>
/// </example>
/// <param name="ink">Color for pixels.</param>
/// <param name="left">Rect to fill.</param>
/// <param name="top">Rect to fill.</param>
/// <param name="width">Rect to fill.</param>
/// <param name="height">Rect to fill.</param>
/// <param name="fill">Draw a solid object.</param>
public void DrawRect(double[] ink, int left, int top, int width, int height, bool? fill = null)
{
var options = new VOption();
options.AddIfPresent(nameof(fill), fill);
this.Call("draw_rect", options, ink, left, top, width, height);
}
/// <summary>
/// Blur a rectangle on an image.
/// </summary>
/// <example>
/// <code language="lang-csharp">
/// image.Mutate(x => x.DrawSmudge(left, top, width, height));
/// </code>
/// </example>
/// <param name="left">Rect to fill.</param>
/// <param name="top">Rect to fill.</param>
/// <param name="width">Rect to fill.</param>
/// <param name="height">Rect to fill.</param>
public void DrawSmudge(int left, int top, int width, int height)
{
this.Call("draw_smudge", left, top, width, height);
}
#endregion
}

153
vendor/NetVips/MutableImage.cs vendored Normal file
View file

@ -0,0 +1,153 @@
using System;
using NetVips.Internal;
using SMath = System.Math;
namespace NetVips;
/// <summary>
/// This class represents a libvips image which can be modified. See
/// <see cref="Image.Mutate"/>.
/// </summary>
public sealed partial class MutableImage : Image
{
/// <summary>
/// The <see cref="Image"/> this <see cref="MutableImage"/> is modifying.
/// Only use this once you have finished all modifications.
/// </summary>
internal Image Image { get; private set; }
/// <summary>
/// Make a <see cref="MutableImage"/> from a regular copied <see cref="Image"/>.
/// </summary>
/// <remarks>
/// This is for internal use only. See <see cref="Image.Mutate"/> for the
/// user-facing interface.
/// </remarks>
internal MutableImage(Image copiedImage) : base(copiedImage.ObjectRef())
{
Image = copiedImage;
}
#region set/remove metadata
/// <summary>
/// Set the type and value of an item of metadata.
/// </summary>
/// <remarks>
/// Sets the type and value of an item of metadata. Any old item of the
/// same name is removed. See <see cref="GValue"/> for types.
/// </remarks>
/// <param name="gtype">The GType of the metadata item to create.</param>
/// <param name="name">The name of the piece of metadata to create.</param>
/// <param name="value">The value to set as a C# value. It is
/// converted to the GType, if possible.</param>
public new void Set(nint gtype, string name, object value)
{
using var gv = new GValue();
gv.SetType(gtype);
gv.Set(value);
VipsImage.Set(this, name, in gv.Struct);
}
/// <summary>
/// Set the value of an item of metadata.
/// </summary>
/// <remarks>
/// Sets the value of an item of metadata. The metadata item must already
/// exist.
/// </remarks>
/// <param name="name">The name of the piece of metadata to set the value of.</param>
/// <param name="value">The value to set as a C# value. It is
/// converted to the type of the metadata item, if possible.</param>
/// <exception cref="T:System.ArgumentException">If metadata item <paramref name="name"/> does not exist.</exception>
public void Set(string name, object value)
{
var gtype = GetTypeOf(name);
if (gtype == IntPtr.Zero)
{
throw new ArgumentException(
$"metadata item {name} does not exist - use the Set(nint, string, object) overload to create and set");
}
Set(gtype, name, value);
}
/// <summary>
/// Remove an item of metadata.
/// </summary>
/// <remarks>
/// The named metadata item is removed.
/// </remarks>
/// <param name="name">The name of the piece of metadata to remove.</param>
/// <returns><see langword="true"/> if the metadata is successfully removed;
/// otherwise, <see langword="false"/>.</returns>
public bool Remove(string name)
{
return VipsImage.Remove(this, name);
}
#endregion
#region overrides
/// <summary>
/// Overload `[]`.
/// </summary>
/// <remarks>
/// Use `[]` to set band elements on an image. For example:
/// <code language="lang-csharp">
/// using var test = image.Mutate(x => x[1] = green);
/// </code>
/// Will change band 1 (the middle band).
/// </remarks>
/// <param name="i">The band element to change.</param>
public new Image this[int i]
{
set
{
// number of bands to the left and right of value
var nLeft = SMath.Min(Bands, SMath.Max(0, i));
var nRight = SMath.Min(Bands, SMath.Max(0, Bands - 1 - i));
var offset = Bands - nRight;
using var left = nLeft > 0 ? Image.ExtractBand(0, n: nLeft) : null;
using var right = nRight > 0 ? Image.ExtractBand(offset, n: nRight) : null;
if (left == null)
{
using (Image)
{
Image = value.Bandjoin(right);
}
}
else if (right == null)
{
using (Image)
{
Image = left.Bandjoin(value);
}
}
else
{
using (Image)
{
Image = left.Bandjoin(value, right);
}
}
}
}
/// <inheritdoc cref="Image"/>
public override Image Mutate(Action<MutableImage> action)
{
action.Invoke(this);
return Image;
}
/// <inheritdoc cref="Image"/>
public override string ToString()
{
return $"<NetVips.MutableImage {Width}x{Height} {Format}, {Bands} bands, {Interpretation}>";
}
#endregion
}

424
vendor/NetVips/NetVips.cs vendored Normal file
View file

@ -0,0 +1,424 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Basic utility stuff.
/// </summary>
public static class NetVips
{
/// <summary>
/// Init() starts up the world of VIPS.
/// </summary>
/// <remarks>
/// This function will be automatically called by <see cref="ModuleInitializer.Initialize"/>
/// once the assembly is loaded. You should only call this method in your own program if the
/// <see cref="ModuleInitializer"/> fails to initialize libvips.
/// </remarks>
/// <returns><see langword="true"/> if successful started; otherwise, <see langword="false"/>.</returns>
public static bool Init()
{
return Vips.Init("NetVips") == 0;
}
/// <summary>
/// Call this to drop caches, close plugins, terminate background threads, and finalize
/// any internal library testing.
/// </summary>
/// <remarks>
/// Calling this is optional. If you don't call it, your platform will clean up for you.
/// The only negative consequences are that the leak checker (<see cref="Leak"/>)
/// and the profiler (<see cref="Profile"/>) will not work.
/// </remarks>
public static void Shutdown()
{
Vips.Shutdown();
}
/// <summary>
/// Enable or disable libvips leak checking.
/// </summary>
/// <remarks>
/// With this enabled, libvips will check for object and area leaks on <see cref="Shutdown"/>.
/// Enabling this option will make libvips run slightly more slowly.
/// </remarks>
public static bool Leak
{
set => Vips.LeakSet(value);
}
/// <summary>
/// Enable or disable libvips profile recording.
/// </summary>
/// <remarks>
/// If set, vips will record profiling information, and dump it on <see cref="Shutdown"/>.
/// These profiles can be analyzed with the `vipsprofile` program.
/// </remarks>
public static bool Profile
{
set => Vips.ProfileSet(value);
}
/// <summary>
/// Gets or sets the number of worker threads libvips' should create to process each image.
/// </summary>
public static int Concurrency
{
get => Vips.ConcurrencyGet();
set => Vips.ConcurrencySet(value);
}
/// <summary>
/// Enable or disable SIMD.
/// </summary>
public static bool Vector
{
get => Vips.VectorIsEnabled();
set => Vips.VectorSet(value);
}
/// <summary>
/// Set the block state on all untrusted operations.
/// </summary>
/// <remarks>
/// For example:
/// <code language="lang-csharp">
/// NetVips.BlockUntrusted = true;
/// </code>
/// Will block all untrusted operations from running. Use:
/// <code language="lang-shell">
/// $ vips -l
/// </code>
/// at the command-line to see the class hierarchy and which
/// operations are marked as untrusted. Use
/// <see cref="Operation.Block"/> to set the block state on
/// specific operations in the libvips class hierarchy.
///
/// At least libvips 8.13 is needed.
/// </remarks>
public static bool BlockUntrusted
{
set => Vips.BlockUntrustedSet(value);
}
/// <summary>
/// Get the major, minor or patch version number of the libvips library.
/// </summary>
/// <param name="flag">Pass 0 to get the major version number, 1 to get minor, 2 to get patch.</param>
/// <param name="fromModule"><see langword="true"/> to get this value from the pre-initialized
/// <see cref="ModuleInitializer.Version"/> variable.</param>
/// <returns>The version number.</returns>
/// <exception cref="T:System.ArgumentOutOfRangeException">If <paramref name="flag"/> is not in range.</exception>
public static int Version(int flag, bool fromModule = true)
{
if (fromModule && ModuleInitializer.Version.HasValue)
{
var version = ModuleInitializer.Version.Value;
switch (flag)
{
case 0:
return (version >> 16) & 0xFF;
case 1:
return (version >> 8) & 0xFF;
case 2:
return version & 0xFF;
}
}
if (flag is < 0 or > 2)
{
throw new ArgumentOutOfRangeException(nameof(flag), "Flag must be in the range of 0 to 2");
}
var value = Vips.Version(flag);
if (value < 0)
{
throw new VipsException("Unable to get library version");
}
return value;
}
/// <summary>
/// Is this at least libvips major.minor[.patch]?
/// </summary>
/// <param name="x">Major component.</param>
/// <param name="y">Minor component.</param>
/// <param name="z">Patch component.</param>
/// <returns><see langword="true"/> if at least libvips major.minor[.patch]; otherwise, <see langword="false"/>.</returns>
public static bool AtLeastLibvips(int x, int y, int z = 0)
{
var major = Version(0);
var minor = Version(1);
var patch = Version(2);
return major > x ||
major == x && minor > y ||
major == x && minor == y && patch >= z;
}
/// <summary>
/// Get a list of all the filename suffixes supported by libvips.
/// </summary>
/// <remarks>
/// At least libvips 8.8 is needed.
/// </remarks>
/// <returns>An array of strings or <see langword="null"/>.</returns>
public static string[] GetSuffixes()
{
if (!AtLeastLibvips(8, 8))
{
return null;
}
var ptrArr = VipsForeign.GetSuffixes();
var names = new List<string>();
var count = 0;
nint strPtr;
while ((strPtr = Marshal.ReadIntPtr(ptrArr, count * IntPtr.Size)) != IntPtr.Zero)
{
var name = Marshal.PtrToStringAnsi(strPtr);
names.Add(name);
GLib.GFree(strPtr);
++count;
}
GLib.GFree(ptrArr);
return names.ToArray();
}
/// <summary>
/// Reports leaks (hopefully there are none) it also tracks and reports peak memory use.
/// </summary>
internal static void ReportLeak()
{
VipsObject.PrintAll();
Console.WriteLine("memory: {0} allocations, {1} bytes", Stats.Allocations, Stats.Mem);
Console.WriteLine("files: {0} open", Stats.Files);
Console.WriteLine("memory: high-water mark: {0}", Stats.MemHighwater.ToReadableBytes());
var errorBuffer = Marshal.PtrToStringAnsi(Vips.ErrorBuffer());
if (!string.IsNullOrEmpty(errorBuffer))
{
Console.WriteLine("error buffer: {0}", errorBuffer);
}
}
#region unit test functions
/// <summary>
/// For testing only.
/// </summary>
/// <param name="path">Path to split.</param>
/// <returns>The filename part of a vips7 path.</returns>
internal static string PathFilename7(string path)
{
return Vips.PathFilename7(path);
}
/// <summary>
/// For testing only.
/// </summary>
/// <param name="path">Path to split.</param>
/// <returns>The mode part of a vips7 path.</returns>
internal static string PathMode7(string path)
{
return Vips.PathMode7(path);
}
/// <summary>
/// For testing only.
/// </summary>
internal static void VipsInterpretationGetType()
{
Vips.InterpretationGetType();
}
/// <summary>
/// For testing only.
/// </summary>
internal static void VipsOperationFlagsGetType()
{
VipsOperation.FlagsGetType();
}
#endregion
/// <summary>
/// Get the GType for a name.
/// </summary>
/// <remarks>
/// Looks up the GType for a nickname. Types below basename in the type
/// hierarchy are searched.
/// </remarks>
/// <param name="basename">Name of base class.</param>
/// <param name="nickname">Search for a class with this nickname.</param>
/// <returns>The GType of the class, or <see cref="IntPtr.Zero"/> if the class is not found.</returns>
public static nint TypeFind(string basename, string nickname)
{
return Vips.TypeFind(basename, nickname);
}
/// <summary>
/// Return the name for a GType.
/// </summary>
/// <param name="type">Type to return name for.</param>
/// <returns>Type name.</returns>
public static string TypeName(nint type)
{
return Marshal.PtrToStringAnsi(GType.Name(type));
}
/// <summary>
/// Return the nickname for a GType.
/// </summary>
/// <param name="type">Type to return nickname for.</param>
/// <returns>Nickname.</returns>
public static string NicknameFind(nint type)
{
return Marshal.PtrToStringAnsi(Vips.NicknameFind(type));
}
/// <summary>
/// Get a list of operations available within the libvips library.
/// </summary>
/// <remarks>
/// This can be useful for documentation generators.
/// </remarks>
/// <returns>A list of operations.</returns>
public static List<string> GetOperations()
{
var allNickNames = new List<string>();
var handle = GCHandle.Alloc(allNickNames);
nint TypeMap(nint type, nint a, nint b)
{
var nickname = NicknameFind(type);
// exclude base classes, for e.g. 'jpegload_base'
if (TypeFind("VipsOperation", nickname) != IntPtr.Zero)
{
var list = (List<string>)GCHandle.FromIntPtr(a).Target;
list.Add(NicknameFind(type));
}
return Vips.TypeMap(type, TypeMap, a, b);
}
try
{
Vips.TypeMap(TypeFromName("VipsOperation"), TypeMap, GCHandle.ToIntPtr(handle), IntPtr.Zero);
}
finally
{
handle.Free();
}
// Sort
allNickNames.Sort();
// Filter duplicates
allNickNames = allNickNames.Distinct().ToList();
return allNickNames;
}
/// <summary>
/// Get a list of enums available within the libvips library.
/// </summary>
/// <returns>A list of enums.</returns>
public static List<string> GetEnums()
{
var allEnums = new List<string>();
var handle = GCHandle.Alloc(allEnums);
nint TypeMap(nint type, nint a, nint b)
{
var nickname = TypeName(type);
var list = (List<string>)GCHandle.FromIntPtr(a).Target;
list.Add(nickname);
return Vips.TypeMap(type, TypeMap, a, b);
}
try
{
Vips.TypeMap(TypeFromName("GEnum"), TypeMap, GCHandle.ToIntPtr(handle), IntPtr.Zero);
}
finally
{
handle.Free();
}
// Sort
allEnums.Sort();
return allEnums;
}
/// <summary>
/// Get all values for a enum (GType).
/// </summary>
/// <param name="type">Type to return enum values for.</param>
/// <returns>A list of values.</returns>
public static Dictionary<string, int> ValuesForEnum(nint type)
{
var typeClass = GType.ClassRef(type);
var enumClass = Marshal.PtrToStructure<GEnumClass>(typeClass);
var values = new Dictionary<string, int>((int)enumClass.NValues);
var ptr = enumClass.Values;
for (var i = 0; i < enumClass.NValues; i++)
{
var enumValue = Marshal.PtrToStructure<GEnumValue>(ptr);
values[enumValue.ValueNick] = enumValue.Value;
ptr += Marshal.SizeOf<GEnumValue>();
}
return values;
}
/// <summary>
/// Return the GType for a name.
/// </summary>
/// <param name="name">Type name to lookup.</param>
/// <returns>Corresponding type ID or <see cref="IntPtr.Zero"/>.</returns>
public static nint TypeFromName(string name)
{
return GType.FromName(name);
}
/// <summary>
/// Extract the fundamental type ID portion.
/// </summary>
/// <param name="type">A valid type ID.</param>
/// <returns>Fundamental type ID.</returns>
public static nint FundamentalType(nint type)
{
return GType.Fundamental(type);
}
/// <summary>
/// Frees the memory pointed to by <paramref name="mem"/>.
/// </summary>
/// <remarks>
/// This is needed for <see cref="Image.WriteToMemory(out ulong)"/>.
/// </remarks>
/// <param name="mem">The memory to free.</param>
public static void Free(nint mem)
{
GLib.GFree(mem);
}
}

31
vendor/NetVips/NetVips.csproj vendored Normal file
View file

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="common.props" />
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
<Platforms>x64;x86;ARM64;ARM32</Platforms>
<Optimize>true</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">true</IsTrimmable>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="$(AssemblyName).Tests" />
<InternalsVisibleTo Include="$(AssemblyName).Samples" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<!-- Constrain the version to 4.5.1, as later versions require .NET Framework 4.6.2.
https://github.com/dotnet/maintenance-packages/issues/42
-->
<PackageReference Include="System.Buffers" Version="[4.5.1]" />
</ItemGroup>
</Project>

270
vendor/NetVips/Operation.cs vendored Normal file
View file

@ -0,0 +1,270 @@
using System;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Wrap a <see cref="VipsOperation"/> object.
/// </summary>
public class Operation : VipsObject
{
/// <inheritdoc cref="VipsObject"/>
private Operation(nint pointer) : base(pointer)
{
}
/// <summary>
/// Create a new <see cref="VipsOperation"/> with the specified nickname.
/// </summary>
/// <remarks>
/// You'll need to set any arguments and build the operation before you can use it. See
/// <see cref="O:Call"/> for a higher-level way to make new operations.
/// </remarks>
/// <param name="operationName">Nickname of operation to create.</param>
/// <returns>The new operation.</returns>
/// <exception cref="VipsException">If the operation doesn't exist.</exception>
public static Operation NewFromName(string operationName)
{
var vop = VipsOperation.New(operationName);
if (vop == IntPtr.Zero)
{
throw new VipsException($"no such operation {operationName}");
}
return new Operation(vop);
}
/// <summary>
/// Set a GObject property. The value is converted to the property type, if possible.
/// </summary>
/// <param name="name">The name of the property to set.</param>
/// <param name="matchImage">A <see cref="Image"/> used as guide.</param>
/// <param name="value">The value.</param>
/// <param name="gtype">The GType of the property.</param>
private void Set(nint gtype, Image matchImage, string name, object value)
{
// if the object wants an image and we have a constant, Imageize it
//
// if the object wants an image array, Imageize any constants in the
// array
if (matchImage != null)
{
if (gtype == GValue.ImageType)
{
value = Image.Imageize(matchImage, value);
}
else if (gtype == GValue.ArrayImageType)
{
if (value is not Array { Rank: 1 } values)
{
throw new ArgumentException(
$"unsupported value type {value.GetType()} for VipsArrayImage");
}
var images = new Image[values.Length];
for (var i = 0; i < values.Length; i++)
{
ref var image = ref images[i];
image = Image.Imageize(matchImage, values.GetValue(i));
}
value = images;
}
}
Set(gtype, name, value);
}
/// <summary>
/// Lookup the set of flags for this operation.
/// </summary>
/// <returns>Flags for this operation.</returns>
public Enums.OperationFlags GetFlags() => VipsOperation.GetFlags(this);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <remarks>
/// Use this method to call any libvips operation. For example:
/// <code language="lang-csharp">
/// using Image blackImage = Operation.Call("black", 10, 10) as Image;
/// </code>
/// See the Introduction for notes on how this works.
/// </remarks>
/// <param name="operationName">Operation name.</param>
/// <param name="args">An arbitrary number and variety of arguments.</param>
/// <returns>A new object.</returns>
public static object Call(string operationName, params object[] args) =>
Call(operationName, null, null, args);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <remarks>
/// Use this method to call any libvips operation. For example:
/// <code language="lang-csharp">
/// using Image blackImage = Operation.Call("black", 10, 10) as Image;
/// </code>
/// See the Introduction for notes on how this works.
/// </remarks>
/// <param name="operationName">Operation name.</param>
/// <param name="kwargs">Optional arguments.</param>
/// <param name="args">An arbitrary number and variety of arguments.</param>
/// <returns>A new object.</returns>
public static object Call(string operationName, VOption kwargs = null, params object[] args) =>
Call(operationName, kwargs, null, args);
/// <summary>
/// Call a libvips operation.
/// </summary>
/// <remarks>
/// Use this method to call any libvips operation. For example:
/// <code language="lang-csharp">
/// using Image blackImage = Operation.Call("black", 10, 10) as Image;
/// </code>
/// See the Introduction for notes on how this works.
/// </remarks>
/// <param name="operationName">Operation name.</param>
/// <param name="kwargs">Optional arguments.</param>
/// <param name="matchImage">A <see cref="Image"/> used as guide.</param>
/// <param name="args">An arbitrary number and variety of arguments.</param>
/// <returns>A new object.</returns>
public static object Call(string operationName, VOption kwargs = null, Image matchImage = null,
params object[] args)
{
// pull out the special string_options kwarg
object stringOptions = null;
kwargs?.Remove("string_options", out stringOptions);
var intro = Introspect.Get(operationName);
if (intro.RequiredInput.Count != args.Length)
{
throw new ArgumentException(
$"unable to call {operationName}: {args.Length} arguments given, but {intro.RequiredInput.Count} required");
}
if (!intro.Mutable && matchImage is MutableImage)
{
throw new VipsException($"unable to call {operationName}: operation must be mutable");
}
nint vop;
using (var op = NewFromName(operationName))
{
// set any string options before any args so they can't be
// overridden
if (stringOptions != null && !op.SetString(stringOptions as string))
{
throw new VipsException($"unable to call {operationName}");
}
// set all required inputs
if (matchImage != null && intro.MemberX.HasValue)
{
var memberX = intro.MemberX.Value;
op.Set(memberX.Type, memberX.Name, matchImage);
}
for (var i = 0; i < intro.RequiredInput.Count; i++)
{
var arg = intro.RequiredInput[i];
op.Set(arg.Type, matchImage, arg.Name, args[i]);
}
// set all optional inputs, if any
if (kwargs != null)
{
foreach (var item in kwargs)
{
var name = item.Key;
var value = item.Value;
if (intro.OptionalInput.TryGetValue(name, out var arg))
{
op.Set(arg.Type, matchImage, name, value);
}
else if (!intro.OptionalOutput.ContainsKey(name))
{
throw new ArgumentException($"{operationName} does not support optional argument: {name}");
}
}
}
// build operation
vop = VipsOperation.Build(op);
if (vop == IntPtr.Zero)
{
Internal.VipsObject.UnrefOutputs(op);
throw new VipsException($"unable to call {operationName}");
}
}
var results = new object[intro.RequiredOutput.Count];
using (var op = new Operation(vop))
{
// get all required results
for (var i = 0; i < intro.RequiredOutput.Count; i++)
{
var arg = intro.RequiredOutput[i];
ref var result = ref results[i];
result = op.Get(arg.Name);
}
// fetch optional output args, if any
if (kwargs != null)
{
var optionalArgs = new VOption();
foreach (var item in kwargs)
{
var name = item.Key;
if (intro.OptionalOutput.ContainsKey(name))
{
optionalArgs[name] = op.Get(name);
}
}
if (optionalArgs.Count > 0)
{
var resultsLength = results.Length;
Array.Resize(ref results, resultsLength + 1);
results[resultsLength] = optionalArgs;
}
}
Internal.VipsObject.UnrefOutputs(op);
}
return results.Length == 1 ? results[0] : results;
}
/// <summary>
/// Set the block state on all operations in the libvips class hierarchy at
/// <paramref name="name"/> and below.
/// </summary>
/// <remarks>
/// For example:
/// <code language="lang-csharp">
/// Operation.Block("VipsForeignLoad", true);
/// Operation.Block("VipsForeignLoadJpeg", false);
/// </code>
/// Will block all load operations, except JPEG. Use:
/// <code language="lang-shell">
/// $ vips -l
/// </code>
/// at the command-line to see the class hierarchy.
/// Use <see cref="NetVips.BlockUntrusted"/> to set the
/// block state on all untrusted operations.
///
/// This call does nothing if the named operation is not found.
/// At least libvips 8.13 is needed.
/// </remarks>
/// <param name="name">Set block state at this point and below.</param>
/// <param name="state">The block state to set.</param>
public static void Block(string name, bool state)
{
VipsOperation.BlockSet(name, state);
}
}

71
vendor/NetVips/Region.cs vendored Normal file
View file

@ -0,0 +1,71 @@
using System;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Wrap a <see cref="VipsRegion"/> object.
/// </summary>
/// <remarks>
/// A region is a small part of an image. You use regions to read pixels
/// out of images without storing the entire image in memory.
/// At least libvips 8.8 is needed.
/// </remarks>
public class Region : VipsObject
{
private Region(nint pointer) : base(pointer)
{
}
/// <summary>
/// Make a region on an image.
/// </summary>
/// <param name="image"><see cref="Image"/> to create this region on.</param>
/// <returns>A new <see cref="Region"/>.</returns>
/// <exception cref="VipsException">If unable to make a new region on <paramref name="image"/>.</exception>
public static Region New(Image image)
{
var vi = VipsRegion.New(image);
if (vi == IntPtr.Zero)
{
throw new VipsException("unable to make region");
}
return new Region(vi);
}
/// <summary>
/// Width of pixels held by region.
/// </summary>
public int Width => VipsRegion.Width(this);
/// <summary>
/// Height of pixels held by region.
/// </summary>
public int Height => VipsRegion.Height(this);
/// <summary>
/// Fetch an area of pixels.
/// </summary>
/// <param name="left">Left edge of area to fetch.</param>
/// <param name="top">Top edge of area to fetch.</param>
/// <param name="width">Width of area to fetch.</param>
/// <param name="height">Height of area to fetch.</param>
/// <returns>An array of bytes filled with pixel data.</returns>
public byte[] Fetch(int left, int top, int width, int height)
{
var pointer = VipsRegion.Fetch(this, left, top, width, height, out var size);
if (pointer == IntPtr.Zero)
{
throw new VipsException("unable to fetch from region");
}
var managedArray = new byte[size];
Marshal.Copy(pointer, managedArray, 0, (int)size);
GLib.GFree(pointer);
return managedArray;
}
}

145
vendor/NetVips/Source.cs vendored Normal file
View file

@ -0,0 +1,145 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace NetVips;
/// <summary>
/// An input connection.
/// </summary>
public partial class Source : Connection
{
/// <summary>
/// Secret ref for <see cref="NewFromMemory(byte[])"/>.
/// </summary>
private GCHandle _dataHandle;
/// <inheritdoc cref="Connection"/>
internal Source(nint pointer) : base(pointer)
{
}
/// <summary>
/// Make a new source from a file descriptor (a small integer).
/// </summary>
/// <remarks>
/// Make a new source that is attached to the descriptor. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromDescriptor(0);
/// </code>
/// Makes a descriptor attached to stdin.
///
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="descriptor">Read from this file descriptor.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="descriptor"/>.</exception>
public static Source NewFromDescriptor(int descriptor)
{
var pointer = Internal.VipsSource.NewFromDescriptor(descriptor);
if (pointer == IntPtr.Zero)
{
throw new VipsException($"can't create source from descriptor {descriptor}");
}
return new Source(pointer);
}
/// <summary>
/// Make a new source from a filename.
/// </summary>
/// <remarks>
/// Make a new source that is attached to the named file. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromFile("myfile.jpg");
/// </code>
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="filename">Read from this filename.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="filename"/>.</exception>
public static Source NewFromFile(string filename)
{
var bytes = Encoding.UTF8.GetBytes(filename + char.MinValue); // Ensure null-terminated string
var pointer = Internal.VipsSource.NewFromFile(bytes);
if (pointer == IntPtr.Zero)
{
throw new VipsException($"can't create source from filename {filename}");
}
return new Source(pointer);
}
/// <summary>
/// Make a new source from a memory object.
/// </summary>
/// <remarks>
/// Make a new source that is attached to the memory object. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromMemory(data);
/// </code>
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="data">The memory object.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="data"/>.</exception>
public static Source NewFromMemory(byte[] data)
{
var handle = GCHandle.Alloc(data, GCHandleType.Pinned);
var pointer = Internal.VipsSource.NewFromMemory(handle.AddrOfPinnedObject(), (nuint)data.Length);
if (pointer == IntPtr.Zero)
{
if (handle.IsAllocated)
{
handle.Free();
}
throw new VipsException("can't create input source from memory");
}
return new Source(pointer) { _dataHandle = handle };
}
/// <summary>
/// Make a new source from a memory object.
/// </summary>
/// <remarks>
/// Make a new source that is attached to the memory object. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromMemory(data);
/// </code>
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="data">The memory object.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="data"/>.</exception>
public static Source NewFromMemory(string data) => NewFromMemory(Encoding.UTF8.GetBytes(data));
/// <summary>
/// Make a new source from a memory object.
/// </summary>
/// <remarks>
/// Make a new source that is attached to the memory object. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromMemory(data);
/// </code>
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="data">The memory object.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="data"/>.</exception>
public static Source NewFromMemory(char[] data) => NewFromMemory(Encoding.UTF8.GetBytes(data));
/// <inheritdoc cref="GObject"/>
protected override void Dispose(bool disposing)
{
// release reference to our secret ref
if (_dataHandle.IsAllocated)
{
_dataHandle.Free();
}
// Call our base Dispose method
base.Dispose(disposing);
}
}

117
vendor/NetVips/SourceCustom.cs vendored Normal file
View file

@ -0,0 +1,117 @@
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
namespace NetVips;
/// <summary>
/// An source you can connect delegates to implement behaviour.
/// </summary>
public class SourceCustom : Source
{
/// <summary>
/// A read delegate.
/// </summary>
/// <remarks>
/// The interface is exactly as <see cref="Stream.Read(byte[], int, int)"/>.
/// The handler is given a number of bytes to fetch, and should return a
/// bytes-like object containing up to that number of bytes. If there is
/// no more data available, it should return <see langword="0"/>.
/// </remarks>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
public delegate int ReadDelegate(byte[] buffer, int length);
/// <summary>
/// A seek delegate.
/// </summary>
/// <remarks>
/// The interface is exactly as <see cref="Stream.Seek"/>. The handler is given
/// parameters for offset and whence with the same meanings. It also returns the
/// new position within the current source.
///
/// Seek handlers are optional. If you do not set one, your source will be
/// treated as unseekable and libvips will do extra caching.
/// </remarks>
/// <param name="offset">A byte offset relative to the <paramref name="origin"/>
/// parameter.</param>
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <returns>The new position within the current source.</returns>
public delegate long SeekDelegate(long offset, SeekOrigin origin);
/// <summary>
/// Attach a read delegate.
/// </summary>
public event ReadDelegate OnRead;
/// <summary>
/// Attach a seek delegate.
/// </summary>
public event SeekDelegate OnSeek;
/// <inheritdoc cref="Source"/>
public SourceCustom() : base(Internal.VipsSourceCustom.New())
{
SignalConnect("read", (Internal.VipsSourceCustom.ReadSignal)ReadHandler);
SignalConnect("seek", (Internal.VipsSourceCustom.SeekSignal)SeekHandler);
}
/// <summary>
/// The internal read handler.
/// </summary>
/// <param name="sourcePtr">The underlying pointer to the source.</param>
/// <param name="buffer">A pointer to an array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <param name="userDataPtr">User data associated with the source.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
internal long ReadHandler(nint sourcePtr, nint buffer, long length, nint userDataPtr)
{
if (length <= 0)
{
return 0;
}
var tempArray = ArrayPool<byte>.Shared.Rent((int)length);
try
{
var readLength = OnRead?.Invoke(tempArray, (int)length);
if (!readLength.HasValue)
{
return -1;
}
if (readLength.Value > 0)
{
Marshal.Copy(tempArray, 0, buffer, readLength.Value);
}
return readLength.Value;
}
catch
{
return -1;
}
finally
{
ArrayPool<byte>.Shared.Return(tempArray);
}
}
/// <summary>
/// The internal seek handler.
/// </summary>
/// <param name="sourcePtr">The underlying pointer to the source.</param>
/// <param name="offset">A byte offset relative to the <paramref name="whence"/>
/// parameter.</param>
/// <param name="whence">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <param name="userDataPtr">User data associated with the source.</param>
/// <returns>The new position within the current source.</returns>
internal long SeekHandler(nint sourcePtr, long offset, int whence, nint userDataPtr)
{
var newPosition = OnSeek?.Invoke(offset, (SeekOrigin)whence);
return newPosition ?? -1;
}
}

88
vendor/NetVips/SourceStream.cs vendored Normal file
View file

@ -0,0 +1,88 @@
using System;
using System.IO;
namespace NetVips;
/// <summary>
/// An source connected to a readable <see cref="Stream"/>.
/// </summary>
internal class SourceStream : SourceCustom
{
/// <summary>
/// Read from this stream.
/// </summary>
private readonly Stream _stream;
/// <summary>
/// The start position within the stream.
/// </summary>
private readonly long _startPosition;
/// <inheritdoc cref="SourceCustom"/>
internal SourceStream(Stream stream)
{
var seekable = stream.CanSeek;
_stream = stream;
_startPosition = seekable ? _stream.Position : 0;
OnRead += Read;
if (seekable)
{
OnSeek += Seek;
}
}
/// <summary>
/// Create a <see cref="SourceStream"/> attached to an <see cref="Stream"/>.
/// </summary>
/// <param name="stream">Read from this stream.</param>
/// <returns>A new <see cref="SourceStream"/>.</returns>
/// <exception cref="T:System.ArgumentException">If <paramref name="stream"/> is not readable.</exception>
internal static SourceStream NewFromStream(Stream stream)
{
if (!stream.CanRead)
{
throw new ArgumentException("The stream should be readable.", nameof(stream));
}
return new SourceStream(stream);
}
/// <summary>
/// Attach a read handler.
/// </summary>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
public int Read(byte[] buffer, int length)
{
return _stream.Read(buffer, 0, length);
}
/// <summary>
/// Attach a seek handler.
/// </summary>
/// <param name="offset">A byte offset relative to the <paramref name="origin"/>
/// parameter.</param>
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
public long Seek(long offset, SeekOrigin origin)
{
try
{
return origin switch
{
SeekOrigin.Begin => _stream.Seek(_startPosition + offset, SeekOrigin.Begin) - _startPosition,
SeekOrigin.Current => _stream.Seek(offset, SeekOrigin.Current) - _startPosition,
SeekOrigin.End => _stream.Seek(offset, SeekOrigin.End) - _startPosition,
_ => -1
};
}
catch
{
return -1;
}
}
}

39
vendor/NetVips/Stats.cs vendored Normal file
View file

@ -0,0 +1,39 @@
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// A class that provides the statistics of memory usage and opened files.
/// </summary>
/// <remarks>
/// libvips watches the total amount of live tracked memory and
/// uses this information to decide when to trim caches.
/// </remarks>
public static class Stats
{
/// <summary>
/// Get the number of active allocations.
/// </summary>
public static int Allocations => Vips.TrackedGetAllocs();
/// <summary>
/// Get the number of bytes currently allocated `vips_malloc()` and friends.
/// </summary>
/// <remarks>
/// libvips uses this figure to decide when to start dropping cache.
/// </remarks>
public static int Mem => Vips.TrackedGetMem();
/// <summary>
/// Returns the largest number of bytes simultaneously allocated via vips_tracked_malloc().
/// </summary>
/// <remarks>
/// Handy for estimating max memory requirements for a program.
/// </remarks>
public static ulong MemHighwater => Vips.TrackedGetMemHighwater();
/// <summary>
/// Get the number of open files.
/// </summary>
public static int Files => Vips.TrackedGetFiles();
}

99
vendor/NetVips/Target.cs vendored Normal file
View file

@ -0,0 +1,99 @@
using System;
using System.Text;
namespace NetVips;
/// <summary>
/// An output connection.
/// </summary>
public class Target : Connection
{
/// <inheritdoc cref="Connection"/>
internal Target(nint pointer) : base(pointer)
{
}
/// <summary>
/// Get the memory object held by the target when using <see cref="NewToMemory"/>.
/// </summary>
public byte[] Blob => (byte[])Get("blob");
/// <summary>
/// Make a new target to write to a file descriptor (a small integer).
/// </summary>
/// <remarks>
/// Make a new target that is attached to the descriptor. For example:
/// <code language="lang-csharp">
/// using var target = Target.NewToDescriptor(1);
/// </code>
/// Makes a descriptor attached to stdout.
///
/// You can pass this target to (for example) <see cref="Image.WriteToTarget"/>.
/// </remarks>
/// <param name="descriptor">Write to this file descriptor.</param>
/// <returns>A new <see cref="Target"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Target"/> from <paramref name="descriptor"/>.</exception>
public static Target NewToDescriptor(int descriptor)
{
var pointer = Internal.VipsTarget.NewToDescriptor(descriptor);
if (pointer == IntPtr.Zero)
{
throw new VipsException($"can't create output target to descriptor {descriptor}");
}
return new Target(pointer);
}
/// <summary>
/// Make a new target to write to a file.
/// </summary>
/// <remarks>
/// Make a new target that will write to the named file. For example:
/// <code language="lang-csharp">
/// using var target = Target.NewToFile("myfile.jpg");
/// </code>
/// You can pass this target to (for example) <see cref="Image.WriteToTarget"/>.
/// </remarks>
/// <param name="filename">Write to this this file.</param>
/// <returns>A new <see cref="Target"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Target"/> from <paramref name="filename"/>.</exception>
public static Target NewToFile(string filename)
{
var bytes = Encoding.UTF8.GetBytes(filename + char.MinValue); // Ensure null-terminated string
var pointer = Internal.VipsTarget.NewToFile(bytes);
if (pointer == IntPtr.Zero)
{
throw new VipsException($"can't create output target to filename {filename}");
}
return new Target(pointer);
}
/// <summary>
/// Make a new target to write to an area of memory.
/// </summary>
/// <remarks>
/// Make a new target that will write to memory. For example:
/// <code language="lang-csharp">
/// using var target = Target.NewToMemory();
/// </code>
/// You can pass this target to (for example) <see cref="Image.WriteToTarget"/>.
///
/// After writing to the target, fetch the bytes from the target object with:
/// <code language="lang-csharp">
/// var bytes = target.Blob;
/// </code>
/// </remarks>
/// <returns>A new <see cref="Target"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Target"/>.</exception>
public static Target NewToMemory()
{
var pointer = Internal.VipsTarget.NewToMemory();
if (pointer == IntPtr.Zero)
{
throw new VipsException("can't create output target to memory");
}
return new Target(pointer);
}
}

180
vendor/NetVips/TargetCustom.cs vendored Normal file
View file

@ -0,0 +1,180 @@
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
namespace NetVips;
/// <summary>
/// An target you can connect delegates to implement behaviour.
/// </summary>
public class TargetCustom : Target
{
/// <summary>
/// A write delegate.
/// </summary>
/// <remarks>
/// The interface is the same as <see cref="Stream.Write(byte[], int, int)"/>.
/// The handler is given a bytes-like object to write. However, the handler MUST
/// return the number of bytes written.
/// </remarks>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The number of bytes to be written to the current target.</param>
/// <returns>The total number of bytes written to the target.</returns>
public delegate long WriteDelegate(byte[] buffer, int length);
/// <summary>
/// A read delegate.
/// </summary>
/// <remarks>
/// libtiff needs to be able to read on targets, unfortunately.
/// </remarks>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
public delegate int ReadDelegate(byte[] buffer, int length);
/// <summary>
/// A seek delegate.
/// </summary>
/// <remarks>
/// libtiff needs to be able to seek on targets, unfortunately.
/// </remarks>
/// <param name="offset">A byte offset relative to the <paramref name="origin"/>
/// parameter.</param>
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <returns>The new position within the current target.</returns>
public delegate long SeekDelegate(long offset, SeekOrigin origin);
/// <summary>
/// A end delegate.
/// </summary>
/// <remarks>
/// This optional handler is called at the end of write. It should do any
/// cleaning up, if necessary.
/// </remarks>
/// <returns>0 on success, -1 on error.</returns>
public delegate int EndDelegate();
/// <summary>
/// Attach a write delegate.
/// </summary>
public event WriteDelegate OnWrite;
/// <summary>
/// Attach a read delegate.
/// </summary>
/// <remarks>
/// This is not called prior libvips 8.13.
/// </remarks>
public event ReadDelegate OnRead;
/// <summary>
/// Attach a seek delegate.
/// </summary>
/// <remarks>
/// This is not called prior libvips 8.13.
/// </remarks>
public event SeekDelegate OnSeek;
/// <summary>
/// Attach a end delegate.
/// </summary>
public event EndDelegate OnEnd;
/// <inheritdoc cref="Target"/>
public TargetCustom() : base(Internal.VipsTargetCustom.New())
{
var vips813 = NetVips.AtLeastLibvips(8, 13);
SignalConnect("write", (Internal.VipsTargetCustom.WriteSignal)WriteHandler);
if (vips813)
{
SignalConnect("read", (Internal.VipsTargetCustom.ReadSignal)ReadHandler);
SignalConnect("seek", (Internal.VipsTargetCustom.SeekSignal)SeekHandler);
}
SignalConnect(vips813 ? "end" : "finish", (Internal.VipsTargetCustom.EndSignal)EndHandler);
}
/// <summary>
/// The internal write handler.
/// </summary>
/// <param name="targetPtr">The underlying pointer to the target.</param>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The number of bytes to be written to the current target.</param>
/// <param name="userDataPtr">User data associated with the target.</param>
/// <returns>The total number of bytes written to the target.</returns>
internal long WriteHandler(nint targetPtr, byte[] buffer, int length, nint userDataPtr)
{
var bytesWritten = OnWrite?.Invoke(buffer, length);
return bytesWritten ?? -1;
}
/// <summary>
/// The internal read handler.
/// </summary>
/// <param name="targetPtr">The underlying pointer to the target.</param>
/// <param name="buffer">A pointer to an array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <param name="userDataPtr">User data associated with the target.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
internal long ReadHandler(nint targetPtr, nint buffer, long length, nint userDataPtr)
{
if (length <= 0)
{
return 0;
}
var tempArray = ArrayPool<byte>.Shared.Rent((int)length);
try
{
var readLength = OnRead?.Invoke(tempArray, (int)length);
if (!readLength.HasValue)
{
return -1;
}
if (readLength.Value > 0)
{
Marshal.Copy(tempArray, 0, buffer, readLength.Value);
}
return readLength.Value;
}
catch
{
return -1;
}
finally
{
ArrayPool<byte>.Shared.Return(tempArray);
}
}
/// <summary>
/// The internal seek handler.
/// </summary>
/// <param name="targetPtr">The underlying pointer to the target.</param>
/// <param name="offset">A byte offset relative to the <paramref name="whence"/>
/// parameter.</param>
/// <param name="whence">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <param name="userDataPtr">User data associated with the target.</param>
/// <returns>The new position within the current target.</returns>
internal long SeekHandler(nint targetPtr, long offset, int whence, nint userDataPtr)
{
var newPosition = OnSeek?.Invoke(offset, (SeekOrigin)whence);
return newPosition ?? -1;
}
/// <summary>
/// The internal end handler.
/// </summary>
/// <param name="targetPtr">The underlying pointer to the target.</param>
/// <param name="userDataPtr">User data associated with the target.</param>
/// <returns>0 on success, -1 on error.</returns>
internal int EndHandler(nint targetPtr, nint userDataPtr)
{
return OnEnd?.Invoke() ?? 0;
}
}

132
vendor/NetVips/TargetStream.cs vendored Normal file
View file

@ -0,0 +1,132 @@
using System;
using System.IO;
namespace NetVips;
/// <summary>
/// An target connected to a writable <see cref="Stream"/>.
/// </summary>
internal class TargetStream : TargetCustom
{
/// <summary>
/// Write to this stream.
/// </summary>
private readonly Stream _stream;
/// <summary>
/// The start position within the stream.
/// </summary>
private readonly long _startPosition;
/// <inheritdoc cref="GObject"/>
internal TargetStream(Stream stream)
{
var readable = stream.CanRead;
var seekable = stream.CanSeek;
_stream = stream;
_startPosition = seekable ? _stream.Position : 0;
OnWrite += Write;
if (readable)
{
OnRead += Read;
}
if (seekable)
{
OnSeek += Seek;
}
OnEnd += End;
}
/// <summary>
/// Create a <see cref="TargetStream"/> which will output to a <see cref="Stream"/>.
/// </summary>
/// <param name="stream">Write to this stream.</param>
/// <returns>A new <see cref="TargetStream"/>.</returns>
/// <exception cref="T:System.ArgumentException">If <paramref name="stream"/> is not writable.</exception>
internal static TargetStream NewFromStream(Stream stream)
{
if (!stream.CanWrite)
{
throw new ArgumentException("The stream should be writable.", nameof(stream));
}
return new TargetStream(stream);
}
/// <summary>
/// Attach a write handler.
/// </summary>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The number of bytes to be written to the current stream.</param>
/// <returns>The total number of bytes written to the stream.</returns>
private long Write(byte[] buffer, int length)
{
try
{
_stream.Write(buffer, 0, length);
}
catch
{
return -1;
}
return length;
}
/// <summary>
/// Attach a read handler.
/// </summary>
/// <param name="buffer">An array of bytes.</param>
/// <param name="length">The maximum number of bytes to be read.</param>
/// <returns>The total number of bytes read into the buffer.</returns>
public int Read(byte[] buffer, int length)
{
return _stream.Read(buffer, 0, length);
}
/// <summary>
/// Attach a seek handler.
/// </summary>
/// <param name="offset">A byte offset relative to the <paramref name="origin"/>
/// parameter.</param>
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the
/// reference point used to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
public long Seek(long offset, SeekOrigin origin)
{
try
{
return origin switch
{
SeekOrigin.Begin => _stream.Seek(_startPosition + offset, SeekOrigin.Begin) - _startPosition,
SeekOrigin.Current => _stream.Seek(offset, SeekOrigin.Current) - _startPosition,
SeekOrigin.End => _stream.Seek(offset, SeekOrigin.End) - _startPosition,
_ => -1
};
}
catch
{
return -1;
}
}
/// <summary>
/// Attach a end handler.
/// </summary>
/// <returns>0 on success, -1 on error.</returns>
public int End()
{
try
{
_stream.Flush();
}
catch
{
return -1;
}
return 0;
}
}

116
vendor/NetVips/VOption.cs vendored Normal file
View file

@ -0,0 +1,116 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace NetVips;
/// <summary>
/// This class wraps a <see cref="Dictionary{TKey,TValue}"/>.
/// This is used to call functions with optional arguments. See <see cref="Operation.Call(string, VOption, object[])"/>.
/// </summary>
public class VOption : IEnumerable<KeyValuePair<string, object>>
{
private readonly Dictionary<string, object> _internalDictionary = new();
/// <summary>
/// Returns an enumerator that iterates through the <see cref="_internalDictionary"/>.
/// </summary>
/// <returns>A <see cref="T:System.Collections.Generic.Dictionary`2.Enumerator"/> structure for the <see cref="_internalDictionary"/>.</returns>
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _internalDictionary.GetEnumerator();
/// <inheritdoc cref="GetEnumerator"/>
IEnumerator IEnumerable.GetEnumerator() => _internalDictionary.GetEnumerator();
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The value associated with the specified key.</returns>
public object this[string key]
{
get => _internalDictionary[key];
set => _internalDictionary[key] = value;
}
/// <summary>
/// Gets a collection containing the keys in the <see cref="_internalDictionary"/>.
/// </summary>
public Dictionary<string, object>.KeyCollection Keys => _internalDictionary.Keys;
/// <summary>
/// Gets the number of key/value pairs contained in the <see cref="_internalDictionary"/>.
/// </summary>
/// <returns>The number of key/value pairs contained in the <see cref="_internalDictionary"/>.</returns>
public int Count => _internalDictionary.Count;
/// <summary>
/// Adds the specified key and value to the <see cref="_internalDictionary"/>.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add. The value can be null for reference types.</param>
public void Add(string key, object value) => _internalDictionary.Add(key, value);
/// <summary>
/// Adds the specified key and value to the <see cref="_internalDictionary"/>, if value is present.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddIfPresent<T>(string key, T? value) where T : struct
{
if (value.HasValue)
{
_internalDictionary.Add(key, value);
}
}
/// <summary>
/// Adds the specified key and class to the <see cref="_internalDictionary"/>, if class is present.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="cls">The value of the element to add.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddIfPresent<T>(string key, T cls) where T : class
{
if (cls != null)
{
_internalDictionary.Add(key, cls);
}
}
/// <summary>
/// Adds the specified key and array to the <see cref="_internalDictionary"/>, if array is present.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="array">The value of the element to add.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddIfPresent<T>(string key, T[] array) where T : struct
{
if (array is { Length: > 0 })
{
_internalDictionary.Add(key, array);
}
}
/// <summary>
/// Determines whether the <see cref="_internalDictionary"/> contains the specified key.
/// </summary>
/// <param name="key">The key to locate in the <see cref="_internalDictionary"/>.</param>
/// <returns><see langword="true"/> if the <see cref="_internalDictionary"/> contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
public bool ContainsKey(string key) => _internalDictionary.ContainsKey(key);
/// <summary>
/// Removes the value with the specified key from the <see cref="_internalDictionary"/>.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
/// <returns><see langword="true"/> if the element is successfully found and removed; otherwise, <see langword="false"/>.</returns>
public bool Remove(string key) => _internalDictionary.Remove(key);
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param>
/// <returns><see langword="true"/> if the <see cref="_internalDictionary"/> contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
public bool TryGetValue(string key, out object value) => _internalDictionary.TryGetValue(key, out value);
}

64
vendor/NetVips/VipsBlob.cs vendored Normal file
View file

@ -0,0 +1,64 @@
using System;
using System.Runtime.InteropServices;
namespace NetVips;
/// <summary>
/// Manage a <see cref="Internal.VipsBlob"/>.
/// </summary>
internal class VipsBlob : SafeHandle
{
/// <summary>
/// Initializes a new instance of the <see cref="VipsBlob"/> class
/// with the specified pointer to wrap around.
/// </summary>
/// <param name="pointer">The pointer to wrap around.</param>
internal VipsBlob(nint pointer) : base(IntPtr.Zero, true)
{
// record the pointer we were given to manage
SetHandle(pointer);
}
/// <summary>
/// Get the data from a <see cref="Internal.VipsBlob"/>.
/// </summary>
/// <param name="length">Return number of bytes of data.</param>
/// <returns>A <see langword="nint"/> containing the data.</returns>
internal nint GetData(out nuint length)
{
return Internal.VipsBlob.Get(this, out length);
}
/// <summary>
/// Decreases the reference count of the blob.
/// When its reference count drops to 0, the blob is finalized (i.e. its memory is freed).
/// </summary>
/// <returns><see langword="true"/> if the handle is released successfully; otherwise,
/// in the event of a catastrophic failure, <see langword="false"/>.</returns>
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
// Free the VipsArea
Internal.VipsArea.Unref(handle);
}
return true;
}
/// <summary>
/// Gets a value indicating whether the handle is invalid.
/// </summary>
/// <returns><see langword="true"/> if the handle is not valid; otherwise, <see langword="false"/>.</returns>
public override bool IsInvalid => handle == IntPtr.Zero;
/// <summary>
/// Get the number of bytes of data.
/// </summary>
internal ulong Length => Marshal.PtrToStructure<Internal.VipsArea.Struct>(handle).Length;
/// <summary>
/// Get the reference count of the blob. Handy for debugging.
/// </summary>
internal int RefCount => Marshal.PtrToStructure<Internal.VipsArea.Struct>(handle).Count;
}

44
vendor/NetVips/VipsException.cs vendored Normal file
View file

@ -0,0 +1,44 @@
using System;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Our own exception class which handles the libvips error buffer.
/// </summary>
public class VipsException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="VipsException"/> class.
/// </summary>
public VipsException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VipsException"/> class with a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public VipsException(string message)
: base($"{message}{Environment.NewLine}{VipsErrorBuffer()}")
{
Vips.ErrorClear();
}
/// <summary>
/// Initializes a new instance of the <see cref="VipsException"/> class with a specified error message
/// and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="inner">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
public VipsException(string message, Exception inner)
: base($"{message}{Environment.NewLine}{VipsErrorBuffer()}", inner)
{
Vips.ErrorClear();
}
private static string VipsErrorBuffer()
{
return Vips.ErrorBuffer().ToUtf8String();
}
}

154
vendor/NetVips/VipsObject.cs vendored Normal file
View file

@ -0,0 +1,154 @@
using System;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Manage a <see cref="Internal.VipsObject"/>.
/// </summary>
public class VipsObject : GObject
{
/// <summary>
/// Attach a post-close delegate. This is called on finalization.
/// </summary>
/// <remarks>
/// Useful for e.g. deleting the file associated with a temp image.
/// </remarks>
public event Action OnPostClose
{
add => SignalConnect("postclose", value);
remove => SignalHandlersDisconnectByFunc(value);
}
/// <inheritdoc cref="GObject"/>
internal VipsObject(nint pointer) : base(pointer)
{
}
/// <summary>
/// Print a table of all active libvips objects. Handy for debugging.
/// </summary>
internal static void PrintAll()
{
GC.Collect();
Internal.VipsObject.PrintAll();
}
/// <summary>
/// slow! eeeeew.
/// </summary>
/// <param name="name">Arg to fetch.</param>
/// <returns>The pspec for this arg.</returns>
private GParamSpec.Struct? GetPspec(string name)
{
var argument = Internal.VipsObject.GetArgument(this, name, out var pspec, out _, out _);
return argument != 0
? default(GParamSpec.Struct?)
: Marshal.PtrToStructure<GParamSpec.Struct>(pspec);
}
/// <summary>
/// Get a GObject property.
/// </summary>
/// <remarks>
/// The value of the property is converted to a C# value.
/// </remarks>
/// <param name="name">Arg to fetch.</param>
/// <returns>The GObject property.</returns>
internal object Get(string name)
{
var pspec = GetPspec(name);
if (!pspec.HasValue)
{
throw new VipsException("Property not found.");
}
var gtype = pspec.Value.ValueType;
using var gv = new GValue();
gv.SetType(gtype);
// this will add a reference for GObject properties, that ref will be
// unreferenced when the GValue is finalized
Internal.GObject.GetProperty(this, name, ref gv.Struct);
return gv.Get();
}
/// <summary>
/// Set a GObject property. The value is converted to the property type, if possible.
/// </summary>
/// <param name="name">The name of the property to set.</param>
/// <param name="value">The value.</param>
/// <param name="gtype">The GType of the property.</param>
internal void Set(nint gtype, string name, object value)
{
using var gv = new GValue();
gv.SetType(gtype);
gv.Set(value);
Internal.GObject.SetProperty(this, name, in gv.Struct);
}
/// <summary>
/// Set a series of properties using a string.
/// </summary>
/// <remarks>
/// For example:
/// "fred=12, tile"
/// "[fred=12]"
/// </remarks>
/// <param name="stringOptions">Arguments as a string.</param>
/// <returns><see langword="true"/> on success; otherwise, <see langword="false"/>.</returns>
internal bool SetString(string stringOptions)
{
var result = Internal.VipsObject.SetFromString(this, stringOptions);
return result == 0;
}
/// <summary>
/// Get the GType of a GObject property.
/// </summary>
/// <param name="name">The name of the GType to get the type of.</param>
/// <returns>A new instance of <see langword="nint"/> initialized to the GType or
/// <see cref="IntPtr.Zero"/> if the property does not exist.</returns>
public nint GetTypeOf(string name)
{
var pspec = GetPspec(name);
if (!pspec.HasValue)
{
// need to clear any error, this is horrible
Vips.ErrorClear();
return IntPtr.Zero;
}
return pspec.Value.ValueType;
}
/// <summary>
/// Get the blurb for a GObject property.
/// </summary>
/// <param name="name">Arg to fetch.</param>
/// <returns>The blurb.</returns>
public string GetBlurb(string name)
{
var pspec = GetPspec(name);
if (!pspec.HasValue)
{
return null;
}
var pspecValue = pspec.Value;
return Marshal.PtrToStringAnsi(GParamSpec.GetBlurb(in pspecValue));
}
/// <summary>
/// Get the description of a GObject.
/// </summary>
/// <returns>The description of a GObject.</returns>
public string GetDescription()
{
return Marshal.PtrToStringAnsi(Internal.VipsObject.GetDescription(this));
}
}

74
vendor/NetVips/VipsProgress.cs vendored Normal file
View file

@ -0,0 +1,74 @@
using System.Runtime.InteropServices;
namespace NetVips;
/// <summary>
/// Records a start time, and counts microseconds elapsed since that time.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct GTimer
{
/// <summary>
/// Monotonic start time, in microseconds.
/// </summary>
public ulong Start;
/// <summary>
/// Monotonic end time, in microseconds.
/// </summary>
public ulong End;
/// <summary>
/// Is the timer currently active?
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool Active;
}
/// <summary>
/// Struct we keep a record of execution time in. Passed to eval signal so
/// it can assess progress.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct VipsProgress
{
/// <summary>
/// Image we are part of.
/// </summary>
private nint Im;
/// <summary>
/// Time we have been running.
/// </summary>
public int Run;
/// <summary>
/// Estimated seconds of computation left.
/// </summary>
public int Eta;
/// <summary>
/// Number of pels we expect to calculate.
/// </summary>
public long TPels;
/// <summary>
/// Number of pels calculated so far.
/// </summary>
public long NPels;
/// <summary>
/// Percent complete.
/// </summary>
public int Percent;
/// <summary>
/// Start time.
/// </summary>
private nint StartPtr;
/// <summary>
/// Start time.
/// </summary>
public GTimer Start => Marshal.PtrToStructure<GTimer>(StartPtr);
}

37
vendor/NetVips/common.props vendored Normal file
View file

@ -0,0 +1,37 @@
<Project>
<PropertyGroup>
<Product>NetVips</Product>
<Description>.NET binding for libvips</Description>
<Copyright>Kleis Auke Wolthuizen</Copyright>
<NeutralLanguage>en-US</NeutralLanguage>
<Authors>Kleis Auke Wolthuizen</Authors>
<PackageTags>libvips;bindings;image-processing</PackageTags>
<PackageProjectUrl>https://kleisauke.github.io/net-vips</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/kleisauke/net-vips</RepositoryUrl>
<CLSCompliant>false</CLSCompliant>
<ComVisible>false</ComVisible>
<LangVersion>11</LangVersion>
<Major>3</Major>
<Minor>1</Minor>
<Revision>0</Revision>
<BuildNumber Condition="'$(APPVEYOR_BUILD_NUMBER)' != ''">$(APPVEYOR_BUILD_NUMBER)</BuildNumber>
<BuildNumber Condition="'$(BuildNumber)' == ''">0</BuildNumber>
<PrereleaseLabel Condition="'$(APPVEYOR_BUILD_NUMBER)' != ''">-develop</PrereleaseLabel>
<PrereleaseLabelConstants></PrereleaseLabelConstants>
<PrereleaseLabelConstants Condition="'$(APPVEYOR_BUILD_NUMBER)' != ''">PRERELEASE_NIGHTLY</PrereleaseLabelConstants>
<DefineConstants>$(DefineConstants);$(PrereleaseLabelConstants)</DefineConstants>
<AssemblyVersion>$(Major).$(Minor).$(Revision).$(BuildNumber)</AssemblyVersion>
<AssemblyFileVersion>$(Major).$(Minor).$(Revision).$(BuildNumber)</AssemblyFileVersion>
<InformationalVersion>$(Major).$(Minor).$(Revision).$(BuildNumber)$(PrereleaseLabel)</InformationalVersion>
<PackageVersion>$(Major).$(Minor).$(Revision).$(BuildNumber)$(PrereleaseLabel)</PackageVersion>
</PropertyGroup>
</Project>

171
vendor/NetVips/net6.0/Image.cs vendored Normal file
View file

@ -0,0 +1,171 @@
#if NET6_0_OR_GREATER
using System;
using System.Runtime.InteropServices;
using NetVips.Internal;
namespace NetVips;
/// <summary>
/// Wrap a <see cref="VipsImage"/> object.
/// </summary>
public partial class Image
{
#region helpers
/// <summary>
/// Find the name of the load operation vips will use to load a buffer.
/// </summary>
/// <remarks>
/// For example "VipsForeignLoadJpegBuffer". You can use this to work out what
/// options to pass to <see cref="NewFromBuffer(ReadOnlySpan{byte}, string, Enums.Access?, Enums.FailOn?, VOption)"/>.
/// </remarks>
/// <param name="data">The buffer to test.</param>
/// <param name="size">Length of the buffer.</param>
/// <returns>The name of the load operation, or <see langword="null"/>.</returns>
private static unsafe string FindLoadBuffer(void* data, ulong size) =>
Marshal.PtrToStringAnsi(VipsForeign.FindLoadBuffer(data, size));
/// <summary>
/// Find the name of the load operation vips will use to load a buffer.
/// </summary>
/// <remarks>
/// For example "VipsForeignLoadJpegBuffer". You can use this to work out what
/// options to pass to <see cref="NewFromBuffer(ReadOnlySpan{byte}, string, Enums.Access?, Enums.FailOn?, VOption)"/>.
/// </remarks>
/// <param name="data">The buffer to test.</param>
/// <returns>The name of the load operation, or <see langword="null"/>.</returns>
public static unsafe string FindLoadBuffer(ReadOnlySpan<byte> data)
{
fixed (byte* dataFixed = data)
{
return FindLoadBuffer(dataFixed, (ulong)data.Length);
}
}
#endregion
#region constructors
/// <summary>
/// Load a formatted image from memory.
/// </summary>
/// <remarks>
/// This behaves exactly as <see cref="NewFromFile"/>, but the image is
/// loaded from the memory object rather than from a file. The memory
/// object can be a string or buffer.
/// </remarks>
/// <param name="data">The memory object to load the image from.</param>
/// <param name="strOptions">Load options as a string. Use <see cref="string.Empty"/> for no options.</param>
/// <param name="access">Hint the expected access pattern for the image.</param>
/// <param name="failOn">The type of error that will cause load to fail. By
/// default, loaders are permissive, that is, <see cref="Enums.FailOn.None"/>.</param>
/// <param name="kwargs">Optional options that depend on the load operation.</param>
/// <returns>A new <see cref="Image"/>.</returns>
/// <exception cref="VipsException">If unable to load from <paramref name="data"/>.</exception>
public static unsafe Image NewFromBuffer(
ReadOnlySpan<byte> 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;
}
}
/// <summary>
/// Wrap an image around a memory array.
/// </summary>
/// <param name="data">A <see cref="ReadOnlyMemory{T}"/>.</param>
/// <param name="width">Image width in pixels.</param>
/// <param name="height">Image height in pixels.</param>
/// <param name="bands">Number of bands.</param>
/// <param name="format">Band format.</param>
/// <returns>A new <see cref="Image"/>.</returns>
/// <exception cref="VipsException">If unable to make image from <paramref name="data"/>.</exception>
public static unsafe Image NewFromMemory<T>(
ReadOnlyMemory<T> 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;
}
/// <summary>
/// Like <see cref="NewFromMemory{T}(ReadOnlyMemory{T}, int, int, int, Enums.BandFormat)"/>, but
/// for <see cref="ReadOnlySpan{T}"/>, so we must copy as it could be allocated on the stack.
/// </summary>
/// <param name="data">A <see cref="ReadOnlySpan{T}"/>.</param>
/// <param name="width">Image width in pixels.</param>
/// <param name="height">Image height in pixels.</param>
/// <param name="bands">Number of bands.</param>
/// <param name="format">Band format.</param>
/// <returns>A new <see cref="Image"/>.</returns>
/// <exception cref="VipsException">If unable to make image from <paramref name="data"/>.</exception>
public static unsafe Image NewFromMemoryCopy<T>(
ReadOnlySpan<T> 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

47
vendor/NetVips/net6.0/Source.cs vendored Normal file
View file

@ -0,0 +1,47 @@
#if NET6_0_OR_GREATER
using System;
namespace NetVips;
/// <summary>
/// An input connection.
/// </summary>
public partial class Source
{
/// <summary>
/// Make a new source from a memory object.
/// </summary>
/// <remarks>
/// Make a new source that is attached to the memory object. For example:
/// <code language="lang-csharp">
/// using var source = Source.NewFromMemory(data);
/// </code>
/// You can pass this source to (for example) <see cref="Image.NewFromSource"/>.
/// </remarks>
/// <param name="data">The memory object.</param>
/// <returns>A new <see cref="Source"/>.</returns>
/// <exception cref="VipsException">If unable to create a new <see cref="Source"/> from <paramref name="data"/>.</exception>
public static unsafe Source NewFromMemory(ReadOnlySpan<byte> data)
{
fixed (byte* dataFixed = data)
{
var ptr = Internal.VipsBlob.Copy(dataFixed, (nuint)data.Length);
if (ptr == IntPtr.Zero)
{
throw new VipsException("can't create input source from memory");
}
using var blob = new VipsBlob(ptr);
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