/// <summary> /// Adds an EXIF property to an image. /// </summary> /// <param name="image"></param> /// <param name="property"></param> public static void AddExifData(Image image, ExifProperty property) { if (image == null) { throw new ArgumentNullException("image"); } if (property == null) { return; } PropertyItem propertyItem; // The .NET interface for GDI+ does not allow instantiation of the // PropertyItem class. Therefore one must be stolen off the Image // and repurposed. GDI+ uses PropertyItem by value so there is no // side effect when changing the values and reassigning to the image. if (image.PropertyItems == null || image.PropertyItems.Length < 1) { propertyItem = ExifWriter.CreatePropertyItem(); } else { propertyItem = image.PropertyItems[0]; } propertyItem.Id = (int)property.Tag; propertyItem.Type = (short)property.Type; Type dataType = ExifDataTypeAttribute.GetDataType(property.Tag); propertyItem.Value = ExifEncoder.ConvertData(dataType, property.Type, property.Value); propertyItem.Len = propertyItem.Value.Length; // This appears to not be necessary ExifWriter.RemoveExifData(image, property.Tag); image.SetPropertyItem(propertyItem); }
/// <summary> /// Converts a property item to an object or array of objects. /// </summary> /// <param name="propertyItem">the property item to convert</param> /// <returns>the property value</returns> public static object FromPropertyItem(PropertyItem propertyItem) { if (propertyItem == null) { return(null); } object data = null; ExifTag tag = ExifTag.Unknown; Type dataType = null; if (Enum.IsDefined(typeof(ExifTag), propertyItem.Id)) { tag = (ExifTag)propertyItem.Id; dataType = ExifDataTypeAttribute.GetDataType(tag); } ExifType type = (ExifType)propertyItem.Type; switch (type) { case ExifType.Ascii: { // The value represents an array of chars terminated with null ('\0') char data = Encoding.ASCII.GetString(propertyItem.Value).TrimEnd('\0'); break; } case ExifType.Byte: { switch (tag) { case ExifTag.MSTitle: case ExifTag.MSSubject: case ExifTag.MSAuthor: case ExifTag.MSKeywords: case ExifTag.MSComments: { // The value represents an array of unicode bytes terminated with null ('\0') char data = Encoding.Unicode.GetString(propertyItem.Value).TrimEnd('\0'); break; } default: { // The value represents an array of bytes data = propertyItem.Value; break; } } break; } case ExifType.Raw: { // The value represents an array of bytes data = propertyItem.Value; break; } case ExifType.UInt16: { // The value represents an array of unsigned 16-bit integers. int count = propertyItem.Len / UInt16Size; ushort[] result = new ushort[count]; for (int i = 0; i < count; i++) { result[i] = ReadUInt16(propertyItem.Value, i * UInt16Size); } data = result; break; } case ExifType.Int32: { // The value represents an array of signed 32-bit integers. int count = propertyItem.Len / Int32Size; int[] result = new int[count]; for (int i = 0; i < count; i++) { result[i] = ReadInt32(propertyItem.Value, i * Int32Size); } data = result; break; } case ExifType.UInt32: { // The value represents an array of unsigned 32-bit integers. int count = propertyItem.Len / UInt32Size; uint[] result = new uint[count]; for (int i = 0; i < count; i++) { result[i] = ReadUInt32(propertyItem.Value, i * UInt32Size); } data = result; break; } case ExifType.Rational: { // The value represents an array of signed rational numbers // Numerator is an Int32 value, denominator a UInt32 value. int count = propertyItem.Len / RationalSize; Rational <int>[] result = new Rational <int> [count]; for (int i = 0; i < count; i++) { result[i] = new Rational <int>( ReadInt32(propertyItem.Value, i * RationalSize), ReadInt32(propertyItem.Value, i * RationalSize + Int32Size)); } data = result; break; } case ExifType.URational: { // The value represents an array of signed rational numbers // Numerator and denominator are UInt32 values. int count = propertyItem.Len / URationalSize; Rational <uint>[] result = new Rational <uint> [count]; for (int i = 0; i < count; i++) { result[i] = new Rational <uint>( ReadUInt32(propertyItem.Value, i * URationalSize), ReadUInt32(propertyItem.Value, i * URationalSize + UInt32Size)); } data = result; break; } default: { data = propertyItem.Value; break; } } return(ExifDecoder.ConvertData(dataType, data)); }