using System; using NetVips.Internal; using SMath = System.Math; namespace NetVips; /// /// This class represents a libvips image which can be modified. See /// . /// public sealed partial class MutableImage : Image { /// /// The this is modifying. /// Only use this once you have finished all modifications. /// internal Image Image { get; private set; } /// /// Make a from a regular copied . /// /// /// This is for internal use only. See for the /// user-facing interface. /// internal MutableImage(Image copiedImage) : base(copiedImage.ObjectRef()) { Image = copiedImage; } #region set/remove metadata /// /// Set the type and value of an item of metadata. /// /// /// Sets the type and value of an item of metadata. Any old item of the /// same name is removed. See for types. /// /// The GType of the metadata item to create. /// The name of the piece of metadata to create. /// The value to set as a C# value. It is /// converted to the GType, if possible. 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); } /// /// Set the value of an item of metadata. /// /// /// Sets the value of an item of metadata. The metadata item must already /// exist. /// /// The name of the piece of metadata to set the value of. /// The value to set as a C# value. It is /// converted to the type of the metadata item, if possible. /// If metadata item does not exist. 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); } /// /// Remove an item of metadata. /// /// /// The named metadata item is removed. /// /// The name of the piece of metadata to remove. /// if the metadata is successfully removed; /// otherwise, . public bool Remove(string name) { return VipsImage.Remove(this, name); } #endregion #region overrides /// /// Overload `[]`. /// /// /// Use `[]` to set band elements on an image. For example: /// /// using var test = image.Mutate(x => x[1] = green); /// /// Will change band 1 (the middle band). /// /// The band element to change. 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); } } } } /// public override Image Mutate(Action action) { action.Invoke(this); return Image; } /// public override string ToString() { return $""; } #endregion }