private IEnumerable <XmpProperty> ProcessAsXmp(BitmapMetadata metadata, Type enumType, decimal priority, int depth) { foreach (string name in this.GetNamesSafely(metadata)) { object value = metadata.GetQuery(name); #if DIAGNOSTICS Console.Write(new String('\t', depth)); Console.WriteLine("{0} => {1}: {2}", name, value != null ? value.GetType().Name : "null", Convert.ToString(value)); #endif if (value is BitmapMetadata) { value = this.ProcessMetadata((BitmapMetadata)value, name, depth); } else if (value is BitmapMetadataBlob) { value = ((BitmapMetadataBlob)value).GetBlobValue(); } IEnumerable <XmpProperty> valueProps = value as IEnumerable <XmpProperty>; if (valueProps != null) { foreach (XmpProperty prop in valueProps) { yield return(prop); } continue; } Enum schema = this.ParseSchema(enumType, name); if (schema == null) { continue; } XmpProperty property = new XmpProperty { Schema = schema, Priority = priority }; property.Value = this.ProcessValue(property, value); if (property.Value == null) { continue; } yield return(property); } }
/// <summary> /// Converts EXIF Rationals into XMP style /// </summary> /// <param name="property"></param> /// <param name="value"></param> /// <returns></returns> private object ProcessRational(XmpProperty property, object value) { if (value == null) { return(null); } switch (Type.GetTypeCode(value.GetType())) { case TypeCode.UInt64: { ulong rational = (ulong)value; uint numerator = (uint)(rational & 0xFFFFFFFFL); uint denominator = (uint)(rational >> 32); value = new Rational <uint>(numerator, denominator, false); break; } case TypeCode.Int64: { long rational = (long)value; int numerator = (int)(rational & 0xFFFFFFFFL); int denominator = (int)(rational >> 32); value = new Rational <int>(numerator, denominator, false); break; } case TypeCode.UInt32: { uint rational = (uint)value; ushort numerator = (ushort)(rational & 0xFFFF); ushort denominator = (ushort)(rational >> 16); value = new Rational <ushort>(numerator, denominator, false); break; } case TypeCode.Int32: { int rational = (int)value; short numerator = (short)(rational & 0xFFFF); short denominator = (short)(rational >> 16); value = new Rational <short>(numerator, denominator, false); break; } case TypeCode.UInt16: { ushort rational = (ushort)value; byte numerator = (byte)(rational & 0xFF); byte denominator = (byte)(rational >> 8); value = new Rational <byte>(numerator, denominator, false); break; } case TypeCode.Int16: { short rational = (short)value; sbyte numerator = (sbyte)(rational & 0xFF); sbyte denominator = (sbyte)(rational >> 8); value = new Rational <sbyte>(numerator, denominator, false); break; } default: { break; } } return(value); }
/// <summary> /// Converts EXIF / TIFF values into XMP style /// </summary> /// <param name="property"></param> /// <param name="value"></param> /// <returns></returns> private object ProcessValue(XmpProperty property, object value) { if (value == null) { return(value); } if (property.ValueType is XmpBasicType) { switch ((XmpBasicType)property.ValueType) { case XmpBasicType.Date: { DateTime date; Array array = value as Array; if (array != null && array.Length == 3) { try { var seconds = 60m * (60m * Convert.ToDecimal(this.ProcessRational(property, array.GetValue(0))) + Convert.ToDecimal(this.ProcessRational(property, array.GetValue(1)))) + Convert.ToDecimal(this.ProcessRational(property, array.GetValue(2))); date = DateTime.MinValue.AddSeconds(Convert.ToDouble(seconds)); value = date.ToString(XmpDateFormat); } catch { } } else if (DateTime.TryParseExact( Convert.ToString(value), ExifDateFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeLocal, out date)) { // clean up to ISO-8601 value = date.ToString(XmpDateFormat); } break; } case XmpBasicType.LangAlt: case XmpBasicType.Text: case XmpBasicType.ProperName: { if (value is byte[]) { if (property.Schema is ExifSchema && ((ExifSchema)property.Schema) == ExifSchema.GPSVersionID) { // GPSVersionID represents version as byte[] value = String.Join(".", ((byte[])value).Select(b => b.ToString()).ToArray()); } else { value = new String(Encoding.UTF8.GetChars((byte[])value)); } value = this.TrimNullTerm((string)value); } else if (!(value is string) && value is IEnumerable) { var strList = ((IEnumerable)value).OfType <string>().Select(str => this.TrimNullTerm(str)).Where(str => !String.IsNullOrEmpty(str)); if (property.Quantity == XmpQuantity.Single) { value = strList.FirstOrDefault(); } else { value = strList; } } else if (value is string) { value = this.TrimNullTerm((string)value); } break; } } } else if (property.ValueType is ExifType) { switch ((ExifType)property.ValueType) { case ExifType.GpsCoordinate: { Array array = value as Array; if (array != null && array.Length == 3) { try { GpsCoordinate gps = new GpsCoordinate(); gps.Degrees = (Rational <uint>) this.ProcessRational(property, array.GetValue(0)); gps.Minutes = (Rational <uint>) this.ProcessRational(property, array.GetValue(1)); gps.Seconds = (Rational <uint>) this.ProcessRational(property, array.GetValue(2)); value = gps.ToString("X"); } catch { } } break; } case ExifType.Rational: { Array array = value as Array; if (array == null) { value = Convert.ToString(this.ProcessRational(property, value)); } else { string[] strArray = new string[array.Length]; for (int i = 0; i < array.Length; i++) { strArray[i] = Convert.ToString(this.ProcessRational(property, array.GetValue(i))); } value = array; } break; } case ExifType.Flash: { ExifTagFlash flash; if (value is ushort) { flash = (ExifTagFlash)value; } else if (value is string) { try { flash = (ExifTagFlash)Enum.Parse(typeof(ExifTagFlash), Convert.ToString(value)); } catch { break; } } else { break; } value = new Dictionary <string, object> { { "Fired", Convert.ToString((flash & ExifTagFlash.FlashFired) == ExifTagFlash.FlashFired) }, { "Return", (int)(flash & (ExifTagFlash.ReturnNotDetected | ExifTagFlash.ReturnDetected)) >> 1 }, { "Mode", (int)(flash & (ExifTagFlash.ModeOn | ExifTagFlash.ModeOff | ExifTagFlash.ModeAuto)) >> 3 }, { "Function", Convert.ToString((flash & ExifTagFlash.NoFlashFunction) == ExifTagFlash.NoFlashFunction) }, { "RedEyeMode", Convert.ToString((flash & ExifTagFlash.RedEyeReduction) == ExifTagFlash.RedEyeReduction) } }; break; } } } return(value); }