using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using NetVips.Internal; namespace NetVips; /// /// Basic utility stuff. /// public static class NetVips { /// /// Init() starts up the world of VIPS. /// /// /// This function will be automatically called by /// once the assembly is loaded. You should only call this method in your own program if the /// fails to initialize libvips. /// /// if successful started; otherwise, . public static bool Init() { return Vips.Init("NetVips") == 0; } /// /// Call this to drop caches, close plugins, terminate background threads, and finalize /// any internal library testing. /// /// /// 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 () /// and the profiler () will not work. /// public static void Shutdown() { Vips.Shutdown(); } /// /// Enable or disable libvips leak checking. /// /// /// With this enabled, libvips will check for object and area leaks on . /// Enabling this option will make libvips run slightly more slowly. /// public static bool Leak { set => Vips.LeakSet(value); } /// /// Enable or disable libvips profile recording. /// /// /// If set, vips will record profiling information, and dump it on . /// These profiles can be analyzed with the `vipsprofile` program. /// public static bool Profile { set => Vips.ProfileSet(value); } /// /// Gets or sets the number of worker threads libvips' should create to process each image. /// public static int Concurrency { get => Vips.ConcurrencyGet(); set => Vips.ConcurrencySet(value); } /// /// Enable or disable SIMD. /// public static bool Vector { get => Vips.VectorIsEnabled(); set => Vips.VectorSet(value); } /// /// Set the block state on all untrusted operations. /// /// /// For example: /// /// NetVips.BlockUntrusted = true; /// /// Will block all untrusted operations from running. Use: /// /// $ vips -l /// /// at the command-line to see the class hierarchy and which /// operations are marked as untrusted. Use /// to set the block state on /// specific operations in the libvips class hierarchy. /// /// At least libvips 8.13 is needed. /// public static bool BlockUntrusted { set => Vips.BlockUntrustedSet(value); } /// /// Get the major, minor or patch version number of the libvips library. /// /// Pass 0 to get the major version number, 1 to get minor, 2 to get patch. /// to get this value from the pre-initialized /// variable. /// The version number. /// If is not in range. 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; } /// /// Is this at least libvips major.minor[.patch]? /// /// Major component. /// Minor component. /// Patch component. /// if at least libvips major.minor[.patch]; otherwise, . 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; } /// /// Get a list of all the filename suffixes supported by libvips. /// /// /// At least libvips 8.8 is needed. /// /// An array of strings or . public static string[] GetSuffixes() { if (!AtLeastLibvips(8, 8)) { return null; } var ptrArr = VipsForeign.GetSuffixes(); var names = new List(); 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(); } /// /// Reports leaks (hopefully there are none) it also tracks and reports peak memory use. /// 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 /// /// For testing only. /// /// Path to split. /// The filename part of a vips7 path. internal static string PathFilename7(string path) { return Vips.PathFilename7(path); } /// /// For testing only. /// /// Path to split. /// The mode part of a vips7 path. internal static string PathMode7(string path) { return Vips.PathMode7(path); } /// /// For testing only. /// internal static void VipsInterpretationGetType() { Vips.InterpretationGetType(); } /// /// For testing only. /// internal static void VipsOperationFlagsGetType() { VipsOperation.FlagsGetType(); } #endregion /// /// Get the GType for a name. /// /// /// Looks up the GType for a nickname. Types below basename in the type /// hierarchy are searched. /// /// Name of base class. /// Search for a class with this nickname. /// The GType of the class, or if the class is not found. public static nint TypeFind(string basename, string nickname) { return Vips.TypeFind(basename, nickname); } /// /// Return the name for a GType. /// /// Type to return name for. /// Type name. public static string TypeName(nint type) { return Marshal.PtrToStringAnsi(GType.Name(type)); } /// /// Return the nickname for a GType. /// /// Type to return nickname for. /// Nickname. public static string NicknameFind(nint type) { return Marshal.PtrToStringAnsi(Vips.NicknameFind(type)); } /// /// Get a list of operations available within the libvips library. /// /// /// This can be useful for documentation generators. /// /// A list of operations. public static List GetOperations() { var allNickNames = new List(); 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)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; } /// /// Get a list of enums available within the libvips library. /// /// A list of enums. public static List GetEnums() { var allEnums = new List(); var handle = GCHandle.Alloc(allEnums); nint TypeMap(nint type, nint a, nint b) { var nickname = TypeName(type); var list = (List)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; } /// /// Get all values for a enum (GType). /// /// Type to return enum values for. /// A list of values. public static Dictionary ValuesForEnum(nint type) { var typeClass = GType.ClassRef(type); var enumClass = Marshal.PtrToStructure(typeClass); var values = new Dictionary((int)enumClass.NValues); var ptr = enumClass.Values; for (var i = 0; i < enumClass.NValues; i++) { var enumValue = Marshal.PtrToStructure(ptr); values[enumValue.ValueNick] = enumValue.Value; ptr += Marshal.SizeOf(); } return values; } /// /// Return the GType for a name. /// /// Type name to lookup. /// Corresponding type ID or . public static nint TypeFromName(string name) { return GType.FromName(name); } /// /// Extract the fundamental type ID portion. /// /// A valid type ID. /// Fundamental type ID. public static nint FundamentalType(nint type) { return GType.Fundamental(type); } /// /// Frees the memory pointed to by . /// /// /// This is needed for . /// /// The memory to free. public static void Free(nint mem) { GLib.GFree(mem); } }