using MetadataExtractor; using MetadataExtractor.Formats.Exif; using System.Globalization; namespace View_by_Distance.Metadata.Models.Stateless; internal abstract class Exif { private static DateTime? GetDateTime(string? value) { DateTime? result; string dateTimeFormat = "yyyy:MM:dd HH:mm:ss"; string alternateFormat = "ddd MMM dd HH:mm:ss yyyy"; if (value is not null && DateTime.TryParse(value, out DateTime dateTime)) result = dateTime; else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) result = dateTime; else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) result = dateTime; else result = null; return result; } private static Shared.Models.AviDirectory GetAviDirectory(IReadOnlyList directories) { Shared.Models.AviDirectory result; MetadataExtractor.Formats.Avi.AviDirectory? aviDirectory = directories.OfType().FirstOrDefault(); if (aviDirectory is null) result = new(null, null, null, null); else { DateTime? dateTimeOriginal; string? duration = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagDuration); string? height = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagHeight); string? width = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagWidth); if (aviDirectory.TryGetDateTime(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal, out DateTime checkDateTime)) dateTimeOriginal = checkDateTime; else dateTimeOriginal = GetDateTime(aviDirectory.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal)); result = new(dateTimeOriginal, duration, height, width); } return result; } private static Shared.Models.ExifDirectoryBase GetExifDirectoryBase(IReadOnlyList directories) { Shared.Models.ExifDirectoryBase result; ExifDirectoryBase? exifDirectoryBase = directories.OfType().FirstOrDefault(); if (exifDirectoryBase is null) result = new(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); else { DateTime? dateTime; DateTime checkDateTime; DateTime? dateTimeOriginal; DateTime? dateTimeDigitized; string? aperture = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagAperture); string? applicationNotes = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagApplicationNotes); string? artist = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagArtist); string? bitsPerSample = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBitsPerSample); string? bodySerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBodySerialNumber); string? cameraOwnerName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCameraOwnerName); string? compressedAverageBitsPerPixel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompressedAverageBitsPerPixel); string? compression = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompression); string? copyright = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCopyright); string? documentName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagDocumentName); string? exifVersion = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExifVersion); string? exposureTime = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExposureTime); string? fileSource = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagFileSource); string? imageDescription = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageDescription); string? imageHeight = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageHeight); string? imageNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageNumber); string? imageUniqueId = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageUniqueId); string? imageWidth = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageWidth); string? isoSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagIsoSpeed); string? lensMake = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensMake); string? lensModel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensModel); string? lensSerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensSerialNumber); string? make = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMake); string? makerNote = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMakernote); string? model = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagModel); string? orientation = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagOrientation); int? orientationValue = orientation is null ? null : exifDirectoryBase.GetInt32(ExifDirectoryBase.TagOrientation); string? rating = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRating); string? ratingPercent = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRatingPercent); string? securityClassification = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSecurityClassification); string? shutterSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagShutterSpeed); string? software = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSoftware); string? timeZone = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZone); string? timeZoneDigitized = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneDigitized); string? timeZoneOriginal = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneOriginal); string? userComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagUserComment); string? winAuthor = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinAuthor); string? winComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinComment); string? winKeywords = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinKeywords); string? winSubject = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinSubject); string? winTitle = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinTitle); string? xResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagXResolution); string? yResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagYResolution); if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime)) dateTime = checkDateTime; else dateTime = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTime)); if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime)) dateTimeOriginal = checkDateTime; else dateTimeOriginal = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeOriginal)); if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime)) dateTimeDigitized = checkDateTime; else dateTimeDigitized = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeDigitized)); result = new(aperture, applicationNotes, artist, bitsPerSample, bodySerialNumber, cameraOwnerName, compressedAverageBitsPerPixel, compression, copyright, dateTime, dateTimeDigitized, dateTimeOriginal, documentName, exifVersion, exposureTime, fileSource, imageDescription, imageHeight, imageNumber, imageUniqueId, imageWidth, isoSpeed, lensMake, lensModel, lensSerialNumber, make, makerNote, model, orientation, orientationValue, rating, ratingPercent, securityClassification, shutterSpeed, software, timeZone, timeZoneDigitized, timeZoneOriginal, userComment, winAuthor, winComment, winKeywords, winSubject, winTitle, xResolution, yResolution); } return result; } private static Shared.Models.FileMetadataDirectory GetFileMetadataDirectory(string file, IReadOnlyList directories) { Shared.Models.FileMetadataDirectory result; MetadataExtractor.Formats.FileSystem.FileMetadataDirectory? fileMetadataDirectory = directories.OfType().FirstOrDefault(); if (fileMetadataDirectory is null) result = new(null, null, null); else { DateTime? fileModifiedDate; string? fileName = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileName); string? fileSize = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileSize); if (fileMetadataDirectory.TryGetDateTime(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate, out DateTime checkDateTime)) fileModifiedDate = checkDateTime; else fileModifiedDate = GetDateTime(fileMetadataDirectory.GetString(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate)); if (fileName is null || !file.EndsWith(fileName)) throw new NotSupportedException($"!{file}.EndsWith({fileName})"); result = new(fileModifiedDate, fileName, fileSize); } return result; } private static Shared.Models.GifHeaderDirectory GetGifHeaderDirectory(IReadOnlyList directories) { Shared.Models.GifHeaderDirectory result; MetadataExtractor.Formats.Gif.GifHeaderDirectory? gifHeaderDirectory = directories.OfType().FirstOrDefault(); if (gifHeaderDirectory is null) result = new(null, null); else { string? imageHeight = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageHeight); string? imageWidth = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth); result = new(imageHeight, imageWidth); } return result; } private static Shared.Models.PhotoshopDirectory GetPhotoshopDirectory(IReadOnlyList directories) { Shared.Models.PhotoshopDirectory result; MetadataExtractor.Formats.Photoshop.PhotoshopDirectory? PhotoshopDirectory = directories.OfType().FirstOrDefault(); if (PhotoshopDirectory is null) result = new(null, null); else { string? jpegQuality = PhotoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagJpegQuality); string? url = PhotoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl); result = new(jpegQuality, url); } return result; } private static Shared.Models.GpsDirectory GetGpsDirectory(IReadOnlyList directories) { Shared.Models.GpsDirectory result; GpsDirectory? gpsDirectory = directories.OfType().FirstOrDefault(); if (gpsDirectory is null) result = new(null, null, null, null, null, null); else { DateTime? timeStamp; string? altitude = gpsDirectory.GetDescription(GpsDirectory.TagAltitude); string? latitude = gpsDirectory.GetDescription(GpsDirectory.TagLatitude); string? latitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLatitudeRef); string? longitude = gpsDirectory.GetDescription(GpsDirectory.TagLongitude); string? longitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLongitudeRef); if (gpsDirectory.TryGetDateTime(GpsDirectory.TagTimeStamp, out DateTime checkDateTime)) timeStamp = checkDateTime; else timeStamp = GetDateTime(gpsDirectory.GetString(GpsDirectory.TagTimeStamp)); result = new(altitude, latitude, latitudeRef, longitude, longitudeRef, timeStamp); } return result; } private static Shared.Models.JpegDirectory GetJpegDirectory(IReadOnlyList directories) { Shared.Models.JpegDirectory result; MetadataExtractor.Formats.Jpeg.JpegDirectory? jpegDirectory = directories.OfType().FirstOrDefault(); if (jpegDirectory is null) result = new(null, null); else { string? imageHeight = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageHeight); string? imageWidth = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth); result = new(imageHeight, imageWidth); } return result; } private static Shared.Models.PngDirectory GetPngDirectory(IReadOnlyList directories) { Shared.Models.PngDirectory result; MetadataExtractor.Formats.Png.PngDirectory? pngDirectory = directories.OfType().FirstOrDefault(); if (pngDirectory is null) result = new(null, null); else { string? imageHeight = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageHeight); string? imageWidth = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageWidth); result = new(imageHeight, imageWidth); } return result; } private static Shared.Models.QuickTimeMovieHeaderDirectory GetQuickTimeMovieHeaderDirectoryDirectory(IReadOnlyList directories) { Shared.Models.QuickTimeMovieHeaderDirectory result; MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory? aviDirectory = directories.OfType().FirstOrDefault(); if (aviDirectory is null) result = new(null); else { DateTime? created; if (aviDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated, out DateTime checkDateTime)) created = checkDateTime; else created = GetDateTime(aviDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated)); result = new(created); } return result; } private static Shared.Models.QuickTimeTrackHeaderDirectory GetQuickTimeTrackHeaderDirectoryDirectory(IReadOnlyList directories) { Shared.Models.QuickTimeTrackHeaderDirectory result; MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory? aviDirectory = directories.OfType().FirstOrDefault(); if (aviDirectory is null) result = new(null); else { DateTime? created; if (aviDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated, out DateTime checkDateTime)) created = checkDateTime; else created = GetDateTime(aviDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated)); result = new(created); } return result; } private static Shared.Models.WebPDirectory GetWebPDirectory(IReadOnlyList directories) { Shared.Models.WebPDirectory result; MetadataExtractor.Formats.WebP.WebPDirectory? WebPDirectory = directories.OfType().FirstOrDefault(); if (WebPDirectory is null) result = new(null, null); else { string? imageHeight = WebPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageHeight); string? imageWidth = WebPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth); result = new(imageHeight, imageWidth); } return result; } internal static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, Shared.Models.DeterministicHashCode deterministicHashCode, System.Drawing.Size? size, IReadOnlyList directories) { Shared.Models.ExifDirectory results; Shared.Models.AviDirectory aviDirectory = GetAviDirectory(directories); Shared.Models.GpsDirectory gpsDirectory = GetGpsDirectory(directories); Shared.Models.PngDirectory pngDirectory = GetPngDirectory(directories); Shared.Models.JpegDirectory jpegDirectory = GetJpegDirectory(directories); Shared.Models.WebPDirectory webPDirectory = GetWebPDirectory(directories); Shared.Models.ExifDirectoryBase exifDirectoryBase = GetExifDirectoryBase(directories); Shared.Models.GifHeaderDirectory gifHeaderDirectory = GetGifHeaderDirectory(directories); Shared.Models.PhotoshopDirectory photoshopDirectory = GetPhotoshopDirectory(directories); Shared.Models.FileMetadataDirectory fileMetadataDirectory = GetFileMetadataDirectory(filePath.FullName, directories); Shared.Models.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory = GetQuickTimeMovieHeaderDirectoryDirectory(directories); Shared.Models.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory = GetQuickTimeTrackHeaderDirectoryDirectory(directories); results = new(aviDirectory, exifDirectoryBase, fileMetadataDirectory, gifHeaderDirectory, gpsDirectory, size?.Height, deterministicHashCode.Id ?? filePath.Id, jpegDirectory, filePath.Name, photoshopDirectory, pngDirectory, quickTimeMovieHeaderDirectory, quickTimeTrackHeaderDirectory, webPDirectory, size?.Width); return results; } internal static string GetMaker(Shared.Models.ExifDirectoryBase exifDirectoryBase) { string result; if (string.IsNullOrEmpty(exifDirectoryBase.Make?.ToString().Trim())) result = "Unknown"; else result = $"{exifDirectoryBase.Make[0].ToString().ToUpper()}{exifDirectoryBase.Make[1..].ToLower()}".Trim(); return result; } }