/// <summary> /// Get the contents of a GValue. /// </summary> /// <remarks> /// The contents of the GValue are read out as a C# type. /// </remarks> /// <returns></returns> public object Get() { // logger.Debug($"Get: this = {this}"); var gtype = GetTypeOf(); var fundamental = GType.GTypeFundamental(gtype); object result; if (gtype == GBoolType) { result = Internal.GValue.GValueGetBoolean(ref Struct) != 0; } else if (gtype == GIntType) { result = Internal.GValue.GValueGetInt(ref Struct); } else if (gtype == GDoubleType) { result = Internal.GValue.GValueGetDouble(ref Struct); } else if (fundamental == GEnumType) { result = FromEnum(gtype, Internal.GValue.GValueGetEnum(ref Struct)); } else if (fundamental == GFlagsType) { result = Internal.GValue.GValueGetFlags(ref Struct); } else if (gtype == GStrType) { result = Internal.GValue.GValueGetString(ref Struct).ToUtf8String(); } else if (gtype == RefStrType) { // don't bother getting the size -- assume these are always // null-terminated C strings ulong psize = 0; result = VipsType.VipsValueGetRefString(ref Struct, ref psize).ToUtf8String(); } else if (gtype == ImageType) { // GValueGetObject() will not add a ref ... that is // held by the gvalue var vi = Internal.GObject.GValueGetObject(ref 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 psize = 0; var intPtr = VipsType.VipsValueGetArrayInt(ref Struct, ref psize); var intArr = new int[psize]; Marshal.Copy(intPtr, intArr, 0, psize); result = intArr; } else if (gtype == ArrayDoubleType) { var psize = 0; var intPtr = VipsType.VipsValueGetArrayDouble(ref Struct, ref psize); var doubleArr = new double[psize]; Marshal.Copy(intPtr, doubleArr, 0, psize); result = doubleArr; } else if (gtype == ArrayImageType) { var psize = 0; var ptrArr = VipsImage.VipsValueGetArrayImage(ref Struct, ref psize); var images = new Image[psize]; for (var i = 0; i < psize; i++) { var vi = Marshal.ReadIntPtr(ptrArr, i * IntPtr.Size); images[i] = new Image(vi); images[i].ObjectRef(); } result = images; } else if (gtype == BlobType) { ulong psize = 0; var array = VipsType.VipsValueGetBlob(ref Struct, ref psize); // Blob types are returned as an array of bytes. var byteArr = new byte[psize]; Marshal.Copy(array, byteArr, 0, (int)psize); result = byteArr; } else { throw new Exception($"unsupported gtype for get {Base.TypeName(gtype)}"); } return(result); }
/// <summary> /// Set a GValue. /// </summary> /// <remarks> /// The value is converted to the type of the GValue, if possible, and /// assigned. /// </remarks> /// <param name="value"></param> public void Set(object value) { // logger.Debug($"Set: value = {value}"); var gtype = GetTypeOf(); var fundamental = GType.GTypeFundamental(gtype); if (gtype == GBoolType) { Internal.GValue.GValueSetBoolean(ref Struct, Convert.ToBoolean(value) ? 1 : 0); } else if (gtype == GIntType) { Internal.GValue.GValueSetInt(ref Struct, Convert.ToInt32(value)); } else if (gtype == GDoubleType) { Internal.GValue.GValueSetDouble(ref Struct, Convert.ToDouble(value)); } else if (fundamental == GEnumType) { Internal.GValue.GValueSetEnum(ref Struct, ToEnum(gtype, value)); } else if (fundamental == GFlagsType) { Internal.GValue.GValueSetFlags(ref Struct, Convert.ToUInt32(value)); } else if (gtype == GStrType) { var pointer = Convert.ToString(value).ToUtf8Ptr(); Internal.GValue.GValueSetString(ref Struct, pointer); GLib.GFree(pointer); } else if (gtype == RefStrType) { var pointer = Convert.ToString(value).ToUtf8Ptr(); VipsType.VipsValueSetRefString(ref Struct, pointer); GLib.GFree(pointer); } else if (fundamental == GObjectType) { if (!(value is GObject gObject)) { throw new Exception( $"unsupported value type {value.GetType()} for gtype {Base.TypeName(gtype)}" ); } Internal.GObject.GValueSetObject(ref Struct, gObject); } else if (gtype == ArrayIntType) { if (!(value is IEnumerable)) { value = new[] { value }; } switch (value) { case int[] ints: VipsType.VipsValueSetArrayInt(ref Struct, ints, ints.Length); break; case double[] doubles: VipsType.VipsValueSetArrayInt(ref Struct, Array.ConvertAll(doubles, Convert.ToInt32), doubles.Length); break; case object[] objects: VipsType.VipsValueSetArrayInt(ref Struct, Array.ConvertAll(objects, Convert.ToInt32), objects.Length); break; default: throw new Exception( $"unsupported value type {value.GetType()} for gtype {Base.TypeName(gtype)}" ); } } else if (gtype == ArrayDoubleType) { if (!(value is IEnumerable)) { value = new[] { value }; } switch (value) { case double[] doubles: VipsType.VipsValueSetArrayDouble(ref Struct, doubles, doubles.Length); break; case int[] ints: VipsType.VipsValueSetArrayDouble(ref Struct, Array.ConvertAll(ints, Convert.ToDouble), ints.Length); break; case object[] objects: VipsType.VipsValueSetArrayDouble(ref Struct, Array.ConvertAll(objects, Convert.ToDouble), objects.Length); break; default: throw new Exception( $"unsupported value type {value.GetType()} for gtype {Base.TypeName(gtype)}" ); } } else if (gtype == ArrayImageType) { if (!(value is Image[] images)) { throw new Exception( $"unsupported value type {value.GetType()} for gtype {Base.TypeName(gtype)}" ); } var size = images.Length; VipsImage.VipsValueSetArrayImage(ref Struct, size); var ptrArr = VipsImage.VipsValueGetArrayImage(ref Struct, IntPtr.Zero); for (var i = 0; i < size; i++) { Marshal.WriteIntPtr(ptrArr, i * IntPtr.Size, images[i].DangerousGetHandle()); // the gvalue needs a ref on each of the images images[i].ObjectRef(); } } else if (gtype == BlobType) { int length; IntPtr memory; switch (value) { case string strValue: length = Encoding.UTF8.GetByteCount(strValue); // We need to set the blob to a copy of the string that vips // can own memory = strValue.ToUtf8Ptr(); break; case byte[] byteArrValue: length = byteArrValue.Length; memory = byteArrValue.ToPtr(); break; case char[] charArrValue: length = Encoding.UTF8.GetByteCount(charArrValue); memory = Encoding.UTF8.GetBytes(charArrValue).ToPtr(); break; default: throw new Exception( $"unsupported value type {value.GetType()} for gtype {Base.TypeName(gtype)}" ); } if (Base.AtLeastLibvips(8, 6)) { VipsType.VipsValueSetBlobFree(ref Struct, memory, (ulong)length); } else { int FreeFn(IntPtr a, IntPtr b) { GLib.GFree(a); return(0); } VipsType.VipsValueSetBlob(ref Struct, FreeFn, memory, (ulong)length); } } else { throw new Exception( $"unsupported gtype for set {Base.TypeName(gtype)}, fundamental {Base.TypeName(fundamental)}, value type {value.GetType()}" ); } }