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
}