private static string GetColorClassString(Directory exifItem) { var colorClassSting = string.Empty; var ratingCounts = exifItem.Tags.Count(p => p.DirectoryName == "IPTC" && p.Name.Contains("0x02dd")); if (ratingCounts >= 1) { var prefsTag = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "IPTC" && p.Name.Contains("0x02dd"))?.Description; // Results for example // 0:1:0:-00001 // ~~~~~~ // 0:8:0:-00001 if (!string.IsNullOrWhiteSpace(prefsTag)) { var prefsTagSplit = prefsTag.Split(":".ToCharArray()); colorClassSting = prefsTagSplit[1]; } return(colorClassSting); } // Xmp readings colorClassSting = GetXmpData(exifItem, "photomechanic:ColorClass"); return(colorClassSting); }
/// <summary> /// [Exif SubIFD] Shutter Speed Value = 1/2403 sec /// </summary> /// <param name="exifItem">item to look in</param> /// <returns>value</returns> private static string GetShutterSpeedValue(Directory exifItem) { var shutterSpeedString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Exif SubIFD" && p.Name == "Shutter Speed Value")?.Description; if (string.IsNullOrEmpty(shutterSpeedString)) { shutterSpeedString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Exif SubIFD" && p.Name == "Exposure Time")?.Description; } // XMP,http://ns.adobe.com/exif/1.0/,exif:ExposureTime,1/20 var exposureTimeXmp = GetXmpData(exifItem, "exif:ExposureTime"); if (string.IsNullOrEmpty(shutterSpeedString) && !string.IsNullOrEmpty(exposureTimeXmp) && exposureTimeXmp.Length <= 20) { return(exposureTimeXmp); } if (shutterSpeedString == null) { return(string.Empty); } // the database has a 20 char limit if (shutterSpeedString.Length >= 20) { return(string.Empty); } // in xmp there is only a field with for example: 1/33 shutterSpeedString = shutterSpeedString.Replace(" sec", string.Empty); return(shutterSpeedString); }
/// <summary> /// [Exif SubIFD] Focal Length /// </summary> /// <returns></returns> private static double GetFocalLength(Directory exifItem) { var focalLengthString = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "Exif SubIFD" && p.Name == "Focal Length")?.Description; // XMP,http://ns.adobe.com/exif/1.0/,exif:FocalLength,11/1 var focalLengthXmp = GetXmpData(exifItem, "exif:FocalLength"); if (string.IsNullOrEmpty(focalLengthString) && !string.IsNullOrEmpty(focalLengthXmp)) { return(Math.Round(MathFraction.Fraction(focalLengthXmp), 5)); } if (string.IsNullOrWhiteSpace(focalLengthString)) { return(0d); } focalLengthString = focalLengthString.Replace(" mm", string.Empty); // Note: focalLengthString: (Dutch) 2,2 or (English) 2.2 based CultureInfo.CurrentCulture float.TryParse(focalLengthString, NumberStyles.Number, CultureInfo.CurrentCulture, out var focalLength); return(Math.Round(focalLength, 5)); }
private static double GetAperture(Directory exifItem) { var apertureString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Exif SubIFD" && p.Name == "Aperture Value")?.Description; if (string.IsNullOrEmpty(apertureString)) { apertureString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Exif SubIFD" && p.Name == "F-Number")?.Description; } // XMP,http://ns.adobe.com/exif/1.0/,exif:FNumber,9/1 var fNumberXmp = GetXmpData(exifItem, "exif:FNumber"); if (string.IsNullOrEmpty(apertureString) && !string.IsNullOrEmpty(fNumberXmp)) { return(MathFraction.Fraction(fNumberXmp)); } if (apertureString == null) { return(0d); } apertureString = apertureString.Replace("f/", string.Empty); // Note: apertureString: (Dutch) 2,2 or (English) 2.2 based CultureInfo.CurrentCulture float.TryParse(apertureString, NumberStyles.Number, CultureInfo.CurrentCulture, out var aperture); return(aperture); }
private void AddDates(MetadataExtractor.Directory xmpData, Photo photo) { var xmpDirectory = xmpData as XmpDirectory; var dateCreated = xmpDirectory.XmpMeta.Properties.SingleOrDefault(p => p.Path == "xmp:CreateDate"); var photoshopDateCreated = xmpDirectory.XmpMeta.Properties.SingleOrDefault(p => p.Path == "photoshop:DateCreated"); var dateModified = xmpDirectory.XmpMeta.Properties.SingleOrDefault(p => p.Path == "xmp:ModifyDate"); if (!String.IsNullOrWhiteSpace(dateCreated?.Value)) { if (DateTime.TryParse(dateCreated.Value, out DateTime takenDate)) { photo.TakenDate = takenDate; } } if (!photo.TakenDate.HasValue && !String.IsNullOrWhiteSpace(photoshopDateCreated?.Value)) { if (DateTime.TryParse(photoshopDateCreated.Value, out DateTime photoshopTakenDate)) { photo.TakenDate = photoshopTakenDate; } } if (!String.IsNullOrWhiteSpace(dateModified?.Value)) { if (DateTime.TryParse(dateCreated.Value, out DateTime modifiedDate)) { photo.ModifiedDate = modifiedDate; } } }
public static FileIndexItem.Rotation GetOrientationFromExifItem(Directory exifItem) { var tCounts = exifItem.Tags.Count(p => p.DirectoryName == "Exif IFD0" && p.Name == "Orientation"); if (tCounts < 1) { return(FileIndexItem.Rotation.DoNotChange); } var caption = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "Exif IFD0" && p.Name == "Orientation")?.Description; // Not unit tested :( switch (caption) { case "Top, left side (Horizontal / normal)": return(FileIndexItem.Rotation.Horizontal); case "Right side, top (Rotate 90 CW)": return(FileIndexItem.Rotation.Rotate90Cw); case "Bottom, right side (Rotate 180)": return(FileIndexItem.Rotation.Rotate180); case "Left side, bottom (Rotate 270 CW)": return(FileIndexItem.Rotation.Rotate270Cw); default: return(FileIndexItem.Rotation.Horizontal); } }
/// <summary> /// [Exif SubIFD] Lens Model = E 18-200mm F3.5-6.3 OSS LE /// </summary> /// <param name="exifItem"></param> /// <returns></returns> private static string GetMakeLensModel(Directory exifItem) { var lensModel = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "Exif SubIFD" && p.Name == "Lens Model")?.Description; return(lensModel == "----" ? string.Empty : lensModel); }
private void AddMetadataLabel(List <string> labels, MetadataExtractor.Directory exifDir, string tagName) { var tag = exifDir.Tags.SingleOrDefault(t => t.Name == tagName); if (!string.IsNullOrWhiteSpace(tag?.Description)) { labels.Add(tag.Description); } }
private void AddExifDates(MetadataExtractor.Directory directory, Photo photo) { var tag = directory.Tags.SingleOrDefault(t => t.Name == "Date/Time"); if (!string.IsNullOrWhiteSpace(tag?.Description) && DateTime.TryParse(tag.Description, out DateTime creationDate)) { photo.TakenDate = creationDate; } }
/// <summary> /// Extract exif data from picture directories. /// </summary> /// <param name="pictureDirectory"></param> /// <param name="pictureExiftag"></param> /// <returns></returns> public string GetExifData(MetadataExtractor.Directory pictureDirectory, int pictureExiftag) { var exifData = pictureDirectory?.GetDescription(pictureExiftag); var pictureExifData = (!string.IsNullOrEmpty(exifData)) ? (pictureExifMetaData.SpaceTabulation + exifData) : pictureExifMetaData.TabEmpty; return(pictureExifData); }
private void AddLabelFromXmpDescription(List <string> labels, MetadataExtractor.Directory xmpData) { var xmpDirectory = xmpData as XmpDirectory; var artworkDesc = xmpDirectory.XmpMeta.Properties.SingleOrDefault(p => p.Path == "Iptc4xmpExt:ArtworkContentDescription"); if (artworkDesc != null) { labels.Add(artworkDesc.Value); } }
private static string GetXmpData(Directory exifItem, string propertyPath) { // for xmp notes if (!(exifItem is XmpDirectory xmpDirectory) || xmpDirectory.XmpMeta == null) { return(string.Empty); } return((from property in xmpDirectory.XmpMeta.Properties.Where(p => !string.IsNullOrEmpty(p.Value)) where property.Path == propertyPath select property.Value).FirstOrDefault()); }
private static string ParseString(Directory subIfd, int tag) { var stringValue = subIfd.GetStringValue(tag); if (stringValue.Bytes != null) { return(stringValue.ToString()); } return(null); }
private static T?ParseRational <T>(Directory directory, int tag, Func <double, T> convert) where T : struct { if (directory.TryGetRational(tag, out var rational)) { var orig = (rational.Numerator / (double)rational.Denominator); // var boxed = (object) orig; return(convert(orig)); } return(null); }
/// <summary> /// Copmare if two exif tags has the same value /// </summary> /// <param name="tag"></param> /// <param name="subDir1"></param> /// <param name="subDif2"></param> /// <returns>true if not null and has the same value</returns> private static bool CompareDir(int tag, MetadataExtractor.Directory subDir1, MetadataExtractor.Directory subDif2) { var width1 = subDir1?.GetDescription(tag); var width2 = subDif2?.GetDescription(tag); if (width1 == null && width2 == null) { return(true); } return(width1 != null && width1.Equals(width2)); }
/// <summary> /// Extracts all tags with names matching the filter from the directory and returns an enumerable of those tags. /// </summary> private static IEnumerable <Tag> ExtractDirectoryTags(MetadataExtractor.Directory dir, Func <Tag, bool> filter) { List <Tag> tags = new List <Tag>(); foreach (Tag t in dir.Tags) { if (filter(t)) { tags.Add(t); } } return(tags); }
private static DateTime?ParseDateTime(Directory gpsDirectory, DateTimeStyles dateTimeStyles) { var timeStamp = gpsDirectory.GetRationalArray(GpsDirectory.TagTimeStamp); var dateStamp = gpsDirectory.GetString(GpsDirectory.TagDateStamp); if (timeStamp == null || dateStamp == null) { return(null); } var hour = ParseRational(timeStamp[0], Convert.ToInt32); var minute = ParseRational(timeStamp[1], Convert.ToInt32); var second = ParseRational(timeStamp[2], Convert.ToInt32);
private static int?GetOrientation(Directory directory) { try { return(directory?.GetInt32(ExifDirectoryBase.TagOrientation)); } catch (Exception) { // ignored } return(null); }
private void AddQuickTimeMetaCreationDate(MetadataExtractor.Directory quickTimeMeta, Photo photo) { var tag = quickTimeMeta.Tags.SingleOrDefault(t => t.Name == QuickTimeMetaDataCreationDateTag); if (tag != null) { var tagValue = (StringValue)quickTimeMeta.GetObject(tag.Type); if (DateTime.TryParse(tagValue.ToString(), out DateTime creationDate)) { photo.TakenDate = creationDate; } } }
private static void AddQuickTimeMetaCreationDate(MetadataExtractor.Directory quickTimeMeta, Photo photo) { var tag = quickTimeMeta.Tags.SingleOrDefault(t => t.Name == "mdta.com.apple.quicktime.creationdate"); if (tag != null) { var tagValue = quickTimeMeta.GetObject(tag.Type) as QuickTimeMetadataValue; if (DateTime.TryParse(tagValue.Value, out DateTime creationDate)) { photo.TakenDate = creationDate; } } }
/// <summary> /// For the location element /// [IPTC] City = Diepenveen /// [IPTC] Province/State = Overijssel /// [IPTC] Country/Primary Location Name = Nederland /// </summary> /// <param name="exifItem"></param> /// <param name="iptcName">City, State or Country</param> /// <param name="xmpPropertyPath">photoshop:State</param> /// <returns></returns> private static string GetLocationPlaces(Directory exifItem, string iptcName, string xmpPropertyPath) { var tCounts = exifItem.Tags.Count(p => p.DirectoryName == "IPTC" && p.Name == iptcName); if (tCounts < 1) { return(GetXmpData(exifItem, xmpPropertyPath)); } var locationCity = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "IPTC" && p.Name == iptcName)?.Description; return(locationCity); }
public static string GetCaptionAbstract(Directory exifItem) { var tCounts = exifItem.Tags.Count(p => p.DirectoryName == "IPTC" && p.Name == "Caption/Abstract"); // Xmp readings if (tCounts == 0) { return(GetXmpData(exifItem, "dc:description[1]")); } var caption = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "IPTC" && p.Name == "Caption/Abstract")?.Description; return(caption); }
private static int?GetHeight(Directory directory) { int[] tags = { ExifDirectoryBase.TagImageHeight, ExifDirectoryBase.TagExifImageHeight }; foreach (var tag in tags) { try { return(directory?.GetInt32(tag)); } catch (Exception) { // ignored } } return(null); }
/// <summary> /// Read "dc:subject" values from XMP /// </summary> /// <param name="exifItem">item</param> /// <returns></returns> private static string GetXmpDataSubject(Directory exifItem) // { if (!(exifItem is XmpDirectory xmpDirectory) || xmpDirectory.XmpMeta == null) { return(string.Empty); } var tagsList = new HashSet <string>(); foreach (var property in xmpDirectory.XmpMeta.Properties.Where(p => !string.IsNullOrEmpty(p.Value))) { if (property.Path.StartsWith("dc:subject[")) { tagsList.Add(property.Value); } } return(HashSetHelper.HashSetToString(tagsList)); }
private static int GetImageSizeInsideLoop(Directory exifItem, string dirName, string typeName) { var ratingCountsJpeg = exifItem.Tags.Count(p => p.DirectoryName == dirName && p.Name.Contains(typeName) && p.Description != "0"); if (ratingCountsJpeg >= 1) { var widthTag = exifItem.Tags .FirstOrDefault(p => p.DirectoryName == dirName && p.Name.Contains(typeName) && p.Description != "0") ?.Description; widthTag = widthTag?.Replace(" pixels", string.Empty); int.TryParse(widthTag, out var widthInt); return(widthInt >= 1 ? widthInt : 0); // (widthInt >= 1) return widthInt) } return(0); }
public static string GetExifKeywords(Directory exifItem) { var tCounts = exifItem.Tags.Count(p => p.DirectoryName == "IPTC" && p.Name == "Keywords"); if (tCounts == 0) { return(GetXmpDataSubject(exifItem)); } var tags = exifItem.Tags.FirstOrDefault( p => p.DirectoryName == "IPTC" && p.Name == "Keywords")?.Description; if (!string.IsNullOrWhiteSpace(tags)) { tags = tags.Replace(";", ", "); } return(tags); }
private void AddGpsMeta(Photo photo, MetadataExtractor.Directory gpsMeta) { var latitudeTag = gpsMeta.Tags.SingleOrDefault(t => t.Name == "GPS Latitude"); var longitudeTag = gpsMeta.Tags.SingleOrDefault(t => t.Name == "GPS Longitude"); var altitudeTag = gpsMeta.Tags.SingleOrDefault(t => t.Name == "GPS Altitude"); if (latitudeTag != null) { photo.Latitude = GetCoordinateFromDegrees(latitudeTag); } if (longitudeTag != null) { photo.Longitude = GetCoordinateFromDegrees(longitudeTag); } if (altitudeTag != null) { photo.Altitude = altitudeTag.Description; } }
private static int GetIsoSpeedValue(Directory exifItem) { var isoSpeedString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Exif SubIFD" && p.Name == "ISO Speed Ratings")?.Description; if (string.IsNullOrEmpty(isoSpeedString)) { isoSpeedString = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Canon Makernote" && p.Name == "Iso")?.Description; if (isoSpeedString == "Auto") { // src: https://github.com/exiftool/exiftool/blob/ // 6b994069d52302062b9d7a462dc27082c4196d95/lib/Image/ExifTool/Canon.pm#L8882 var autoIso = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Canon Makernote" && p.Name == "Auto ISO")?.Description; var baseIso = exifItem.Tags.FirstOrDefault(p => p.DirectoryName == "Canon Makernote" && p.Name == "Base ISO")?.Description; if (!string.IsNullOrEmpty(autoIso) && !string.IsNullOrEmpty(baseIso)) { int.TryParse(autoIso, NumberStyles.Number, CultureInfo.InvariantCulture, out var autoIsoSpeed); int.TryParse(baseIso, NumberStyles.Number, CultureInfo.InvariantCulture, out var baseIsoSpeed); return(baseIsoSpeed * autoIsoSpeed / 100); } } } // XMP,http://ns.adobe.com/exif/1.0/,exif:ISOSpeedRatings, // XMP,,exif:ISOSpeedRatings[1],101 // XMP,,exif:ISOSpeedRatings[2],101 var isoSpeedXmp = GetXmpData(exifItem, "exif:ISOSpeedRatings[1]"); if (string.IsNullOrEmpty(isoSpeedString) && !string.IsNullOrEmpty(isoSpeedXmp)) { isoSpeedString = isoSpeedXmp; } int.TryParse(isoSpeedString, NumberStyles.Number, CultureInfo.InvariantCulture, out var isoSpeed); return(isoSpeed); }
/// <summary> /// Requires exifDirectory is an actual metadata exif directory. /// Attempts to return the tags that have 'date' in their names /// </summary> private static IEnumerable <Tag> ExtractExIfDateTags(MetadataExtractor.Directory exifDirectory) { return(ExtractDirectoryTags(exifDirectory, n => { return n.Name.ToLower().Contains("date"); })); }
public Tag(int tagType, [NotNull] Directory directory) { TagType = tagType; _directory = directory; }
private static int?ParseInt(Directory directory, int tag) { return(directory.TryGetInt32(tag, out var intValue) ? intValue : (int?)null); }