/// <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> /// <remarks> /// Use this method to call any libvips operation. For example: /// <code language="lang-csharp"> /// var blackImage = Operation.call("black", 10, 10); /// </code> /// See the Introduction for notes on how this works. /// </remarks> /// <param name="operationName"></param> /// <param name="kwargs"></param> /// <param name="args"></param> /// <returns></returns> public static object Call(string operationName, VOption kwargs, params object[] args) { // logger.Debug($"VipsOperation.call: operationName = {operationName}"); // logger.Debug($"VipsOperation.call: args = {args}, kwargs = {kwargs}"); // pull out the special string_options kwarg object stringOptions = null; kwargs?.Remove("string_options", out stringOptions); // logger.Debug($"VipsOperation.call: stringOptions = {stringOptions}"); var op = NewFromName(operationName); var arguments = op.GetArgs(); // logger.Debug($"VipsOperation.call: arguments = {arguments}"); // make a thing to quickly get flags from an arg name var flagsFromName = new Dictionary <string, Internal.Enums.VipsArgumentFlags>(); var nRequired = 0; foreach (var entry in arguments) { var name = entry.Key; var flag = entry.Value; flagsFromName[name] = flag; // count required input args if ((flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_INPUT) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_REQUIRED) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_DEPRECATED) == 0) { nRequired++; } } if (nRequired != args.Length) { throw new ArgumentException( $"unable to call {operationName}: {args.Length} arguments given, but {nRequired} required"); } // the first image argument is the thing we expand constants to // match ... look inside tables for images, since we may be passing // an array of image as a single param var matchImage = FindInside <Image>(args); // logger.Debug($"VipsOperation.call: matchImage = {matchImage}"); // 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 required and optional args var n = 0; foreach (var entry in arguments) { var name = entry.Key; var flag = entry.Value; if ((flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_INPUT) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_REQUIRED) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_DEPRECATED) == 0) { op.Set(name, flag, matchImage, args[n]); n++; } } if (kwargs != null) { foreach (var entry in kwargs) { var name = entry.Key; var value = entry.Value; if (!flagsFromName.ContainsKey(name)) { throw new Exception($"{operationName} does not support argument {name}"); } op.Set(name, flagsFromName[name], matchImage, value); } } // build operation var vop = VipsOperation.VipsCacheOperationBuild(op); if (vop == IntPtr.Zero) { throw new VipsException($"unable to call {operationName}"); } op = new Operation(vop); // fetch required output args, plus modified input images var result = new List <object>(); foreach (var entry in arguments) { var name = entry.Key; var flag = entry.Value; if ((flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_OUTPUT) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_REQUIRED) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_DEPRECATED) == 0) { result.Add(op.Get(name)); } if ((flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_INPUT) != 0 && (flag & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_MODIFY) != 0) { result.Add(op.Get(name)); } } // fetch optional output args var opts = new VOption(); if (kwargs != null) { foreach (var entry in kwargs) { var name = entry.Key; var flags = flagsFromName[name]; if ((flags & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_OUTPUT) != 0 && (flags & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_REQUIRED) == 0 && (flags & Internal.Enums.VipsArgumentFlags.VIPS_ARGUMENT_DEPRECATED) == 0) { opts[name] = op.Get(name); } } } Internal.VipsObject.VipsObjectUnrefOutputs(op); if (opts.Count > 0) { result.Add(opts); } // logger.Debug($"VipsOperation.call: result = {result}"); return(result.Count == 0 ? null : (result.Count == 1 ? result[0] : result.ToArray())); }
/// <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> /// 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> /// Call a libvips operation. /// </summary> /// <param name="image"></param> /// <param name="operationName"></param> /// <param name="kwargs"></param> /// <param name="args"></param> /// <returns></returns> public static object Call(this Image image, string operationName, VOption kwargs, params object[] args) { return(Operation.Call(operationName, kwargs, args.PrependImage(image))); }
/// <summary> /// Call a libvips operation. /// </summary> /// <param name="image"></param> /// <param name="operationName"></param> /// <param name="kwargs"></param> /// <param name="arg"></param> /// <returns></returns> public static object Call(this Image image, string operationName, VOption kwargs, object arg) { return(Operation.Call(operationName, kwargs, image, arg)); }