Metadata
This commit is contained in:
parent
c2c711673f
commit
ec22446643
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -22,6 +22,8 @@
|
||||
"Hmmssfff",
|
||||
"jfif",
|
||||
"JOSN",
|
||||
"Makernote",
|
||||
"Makernotes",
|
||||
"mmod",
|
||||
"Nicéphore",
|
||||
"Niépce",
|
||||
@ -31,6 +33,7 @@
|
||||
"permyriad",
|
||||
"Phares",
|
||||
"Phgtv",
|
||||
"photoshop",
|
||||
"RDHC",
|
||||
"Rects",
|
||||
"resnet",
|
||||
|
@ -8,7 +8,7 @@ using View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
namespace View_by_Distance.Distance.Models;
|
||||
|
||||
public partial class E_Distance : IDistance<MetadataExtractor.Directory>
|
||||
public partial class E_Distance : IDistance
|
||||
{
|
||||
|
||||
internal record Record(FilePath FilePath, FaceRecognitionDotNet.FaceEncoding FaceRecognitionDotNetFaceEncoding);
|
||||
@ -201,7 +201,7 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
|
||||
}
|
||||
}
|
||||
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, FilePath filePath, MappingFromItem mappingFromItem, List<Face> faces, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
public void LookForMatchFacesAndPossiblyRename(string facesFileNameExtension, FilePath filePath, MappingFromItem mappingFromItem, List<Face> faces, ReadOnlyCollection<LocationContainer> locationContainers)
|
||||
{
|
||||
string? json;
|
||||
string[] matches;
|
||||
@ -212,20 +212,20 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
|
||||
Face[] filteredFaces = (from l in faces where l.FaceEncoding is not null && l.Location is not null && l.OutputResolution is not null select l).ToArray();
|
||||
if (filteredFaces.Length != faces.Count)
|
||||
checkFaces.Clear();
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (_Renamed.Contains(locationContainer.FilePath.FullName))
|
||||
continue;
|
||||
if (locationContainer.FromDistanceContent && _DuplicateMappedFaceFiles.Contains(locationContainer.FilePath.Name))
|
||||
continue;
|
||||
checkFaces.Clear();
|
||||
if (locationContainer.Directories.Count == 0)
|
||||
if (locationContainer.ExifDirectory is null)
|
||||
{
|
||||
if (locationContainer.FromDistanceContent)
|
||||
throw new NullReferenceException(nameof(locationContainer.Directories));
|
||||
throw new NullReferenceException(nameof(locationContainer.ExifDirectory));
|
||||
continue;
|
||||
}
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetFaceEncoding(locationContainer.Directories);
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetFaceEncoding(locationContainer.ExifDirectory);
|
||||
if (json is null)
|
||||
{
|
||||
if (_DistanceMoveUnableToMatch)
|
||||
@ -520,16 +520,16 @@ public partial class E_Distance : IDistance<MetadataExtractor.Directory>
|
||||
return new(results);
|
||||
}
|
||||
|
||||
ReadOnlyCollection<RelationContainer> IDistance<MetadataExtractor.Directory>.GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
ReadOnlyCollection<RelationContainer> IDistance.GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer> locationContainers)
|
||||
{
|
||||
ReadOnlyCollection<RelationContainer> result;
|
||||
string? json;
|
||||
List<Record> records = [];
|
||||
Shared.Models.FaceEncoding? modelsFaceEncoding;
|
||||
FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding;
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetFaceEncoding(locationContainer.Directories);
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetFaceEncoding(locationContainer.ExifDirectory);
|
||||
if (json is null)
|
||||
continue;
|
||||
modelsFaceEncoding = JsonSerializer.Deserialize<Shared.Models.FaceEncoding>(json);
|
||||
|
@ -7,7 +7,6 @@ using System.Text;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Drag.Drop.Set.Item.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
|
||||
namespace View_by_Distance.Drag.Drop.Set.Item;
|
||||
@ -178,7 +177,7 @@ public partial class DragDropSetPropertyItem : Form
|
||||
{
|
||||
short type = 1;
|
||||
ASCIIEncoding asciiEncoding = new();
|
||||
int xpKeywords = (int)IExif.Tags.XPKeywords;
|
||||
int xpKeywords = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinKeywords;
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, [], null) ?? throw new Exception();
|
||||
List<Record> records = GetRecords(asciiEncoding, xpKeywords, files);
|
||||
if (records.Count == 0)
|
||||
|
@ -162,10 +162,10 @@ public class D_Face
|
||||
string faceEncodingJson;
|
||||
PropertyItem? propertyItem;
|
||||
string outputResolutionJson;
|
||||
int artist = (int)IExif.Tags.Artist;
|
||||
int fileSource = (int)IExif.Tags.FileSource;
|
||||
int userComment = (int)IExif.Tags.UserComment;
|
||||
using Bitmap source = new(resizedFileHolder.FullName);
|
||||
int artist = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist;
|
||||
int fileSource = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagFileSource;
|
||||
int userComment = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagUserComment;
|
||||
foreach ((Shared.Models.Face face, FileInfo? fileInfo, string fileName, bool save) in collection)
|
||||
{
|
||||
if (!save)
|
||||
@ -260,9 +260,9 @@ public class D_Face
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(string outputResolution, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
|
||||
private static List<LocationContainer> GetLocationContainers(string outputResolution, ReadOnlyCollection<LocationContainer> locationContainers, Dictionary<string, int[]> outputResolutionToResize, List<Shared.Models.Face> faces)
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>> results = [];
|
||||
List<LocationContainer> results = [];
|
||||
string? json;
|
||||
Location? location;
|
||||
Rectangle? rectangle;
|
||||
@ -275,9 +275,9 @@ public class D_Face
|
||||
continue;
|
||||
skip.Add(Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution));
|
||||
}
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (locationContainer.Directories is null)
|
||||
if (locationContainer.ExifDirectory is null)
|
||||
continue;
|
||||
if (skip.Contains(locationContainer.WholePercentages))
|
||||
continue;
|
||||
@ -285,7 +285,7 @@ public class D_Face
|
||||
{
|
||||
if (face.Location is not null && face.OutputResolution is not null)
|
||||
continue;
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetOutputResolution(locationContainer.Directories);
|
||||
json = Metadata.Models.Stateless.Methods.IMetadata.GetOutputResolution(locationContainer.ExifDirectory);
|
||||
if (json is null)
|
||||
continue;
|
||||
outputResolutionCheck = JsonSerializer.Deserialize<OutputResolution>(json);
|
||||
@ -299,7 +299,7 @@ public class D_Face
|
||||
continue;
|
||||
if (!results.Any(l => l.WholePercentages == locationContainer.WholePercentages))
|
||||
results.Add(new(locationContainer.CreationDateOnly,
|
||||
locationContainer.Directories,
|
||||
locationContainer.ExifDirectory,
|
||||
locationContainer.DirectoryNumber,
|
||||
locationContainer.DisplayDirectoryName,
|
||||
locationContainer.FilePath,
|
||||
@ -316,7 +316,7 @@ public class D_Face
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>>? locationContainers, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
public List<Shared.Models.Face> GetFaces(string outputResolution, string dResultsFullGroupDirectory, FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary<string, int[]> outputResolutionToResize, ReadOnlyCollection<LocationContainer>? locationContainers, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection)
|
||||
{
|
||||
List<Shared.Models.Face>? results;
|
||||
if (string.IsNullOrEmpty(dResultsFullGroupDirectory))
|
||||
@ -359,7 +359,7 @@ public class D_Face
|
||||
parseExceptions.Add(nameof(D_Face));
|
||||
}
|
||||
}
|
||||
List<LocationContainer<MetadataExtractor.Directory>> collection;
|
||||
List<LocationContainer> collection;
|
||||
if (results is null || locationContainers is null)
|
||||
collection = [];
|
||||
else
|
||||
|
@ -788,7 +788,7 @@ public partial class DlibDotNet
|
||||
_Logger?.LogInformation(string.Concat("Moved <", item.ImageFileHolder.FullName, '>'));
|
||||
}
|
||||
|
||||
private int GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> faces)
|
||||
private int GetNotMappedCountAndUpdateMappingFromPersonThenSetMapping(MapLogic mapLogic, Item item, bool? isFocusRelativePath, ReadOnlyCollection<LocationContainer> locationContainers, MappingFromItem mappingFromItem, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, List<Shared.Models.Face> faces)
|
||||
{
|
||||
int result;
|
||||
double? α;
|
||||
@ -951,7 +951,7 @@ public partial class DlibDotNet
|
||||
string[] changesFrom = [nameof(A_Property)];
|
||||
List<Tuple<string, DateTime>> subFileTuples = [];
|
||||
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
|
||||
ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers = mapLogic.GetLocationContainers(item);
|
||||
ReadOnlyCollection<LocationContainer> locationContainers = mapLogic.GetLocationContainers(item);
|
||||
if (item.Property is null || item.Property.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
|
||||
{
|
||||
LogItemPropertyIsNull(item);
|
||||
@ -993,14 +993,14 @@ public partial class DlibDotNet
|
||||
throw new NullReferenceException(nameof(property));
|
||||
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
|
||||
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
|
||||
ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
Map.Models.Stateless.Methods.IMapLogic.SetCreationTimeMaybeMoveToDecade(_Configuration.PropertyConfiguration, _Configuration.MoveToDecade && _Configuration.LocationContainerDistanceTolerance is null, mappingFromItem, locationContainers);
|
||||
ReadOnlyDictionary<string, MetadataExtractorDirectory> metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
if (_AppSettings.Places.Count > 0)
|
||||
{
|
||||
float latitude;
|
||||
float longitude;
|
||||
double? distance;
|
||||
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(metadataExtractorDirectories);
|
||||
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(exifDirectory);
|
||||
foreach (Place place in _AppSettings.Places)
|
||||
{
|
||||
if (geoLocation is null)
|
||||
|
@ -194,11 +194,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
private void LookForAbandoned(Property.Models.Configuration propertyConfiguration, List<int> distinctFilteredIds)
|
||||
{
|
||||
List<string> renameCollection = [];
|
||||
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in _IdToLocationContainers)
|
||||
foreach (KeyValuePair<int, List<LocationContainer>> keyValuePair in _IdToLocationContainers)
|
||||
{
|
||||
if (distinctFilteredIds.Contains(keyValuePair.Key))
|
||||
continue;
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in keyValuePair.Value)
|
||||
foreach (LocationContainer locationContainer in keyValuePair.Value)
|
||||
{
|
||||
if (locationContainer.FilePath.FullName.Contains('!'))
|
||||
continue;
|
||||
@ -217,10 +217,10 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
private readonly ReadOnlyDictionary<int, List<int>> _SkipCollection;
|
||||
private readonly ReadOnlyDictionary<int, List<int>> _SkipNotSkipCollection;
|
||||
private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration;
|
||||
private readonly ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> _IdToLocationContainers;
|
||||
private readonly ReadOnlyDictionary<int, List<LocationContainer>> _IdToLocationContainers;
|
||||
private readonly ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> _IdThenWholePercentagesToPersonContainers;
|
||||
|
||||
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, ReadOnlyCollection<PersonContainer> personContainers, long ticks, string? a2PeopleContentDirectory, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
|
||||
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, Shared.Models.Methods.IDistance distance, ReadOnlyCollection<PersonContainer> personContainers, long ticks, string? a2PeopleContentDirectory, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
|
||||
{
|
||||
_Ticks = ticks;
|
||||
_Configuration = configuration;
|
||||
@ -229,7 +229,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
List<PersonContainer> notMappedPersonContainers = [];
|
||||
Dictionary<int, List<(string, int)>> skipCollection = [];
|
||||
Dictionary<int, List<(string, int)>> skipNotSkipCollection = [];
|
||||
List<LocationContainer<MetadataExtractor.Directory>> locationContainers = [];
|
||||
List<LocationContainer> locationContainers = [];
|
||||
string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory);
|
||||
string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, ticks.ToString());
|
||||
ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> idThenWholePercentagesToPersonContainers;
|
||||
@ -332,14 +332,14 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(Item item)
|
||||
public ReadOnlyCollection<LocationContainer> GetLocationContainers(Item item)
|
||||
{
|
||||
LocationContainer<MetadataExtractor.Directory>[] results;
|
||||
LocationContainer[] results;
|
||||
if (item.Property?.Id is null)
|
||||
results = [];
|
||||
else
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>>? locationContainers;
|
||||
List<LocationContainer>? locationContainers;
|
||||
if (_IdToLocationContainers.TryGetValue(item.Property.Id.Value, out locationContainers))
|
||||
results = locationContainers.ToArray();
|
||||
else
|
||||
@ -678,17 +678,17 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
||||
if (j == i)
|
||||
continue;
|
||||
if (face.Mapping.MappingFromFilterPre.InSkipCollection is not null && face.Mapping.MappingFromFilterPre.InSkipCollection.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
if (face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
if (face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
if (face.Mapping.MappingFromFilterPost.InSkipCollection is not null && face.Mapping.MappingFromFilterPost.InSkipCollection.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
if (face.Mapping.MappingFromFilterPost.IsFocusPerson is not null && !face.Mapping.MappingFromFilterPost.IsFocusPerson.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
if (face.Mapping.MappingFromFilterPost.InSkipCollection is not null && face.Mapping.MappingFromFilterPost.InSkipCollection.Value)
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance<object>));
|
||||
throw new NotSupportedException(nameof(Shared.Models.Methods.IDistance));
|
||||
faceDistanceLength = faceDistanceLengths[j];
|
||||
if (faceDistanceLength.WholePercentages is null || faceDistanceLength.Length is null)
|
||||
throw new NotSupportedException();
|
||||
|
@ -32,7 +32,7 @@ internal abstract class DecadeLogic
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
internal static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, MappingFromItem mappingFromItem, ReadOnlyCollection<LocationContainer> locationContainers)
|
||||
{
|
||||
DateTime dateTime;
|
||||
string halfDecade;
|
||||
@ -42,7 +42,7 @@ internal abstract class DecadeLogic
|
||||
string personNameDirectoryName;
|
||||
string? personKeyFormattedDirectory;
|
||||
string? personKeyFormattedDirectoryName;
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (!File.Exists(locationContainer.FilePath.FullName))
|
||||
continue;
|
||||
|
@ -470,7 +470,7 @@ internal abstract class MapLogic
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, MappedFile mappedFile)
|
||||
private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer> locationContainers, MappedFile mappedFile)
|
||||
{
|
||||
int? id;
|
||||
string checkFile;
|
||||
@ -480,9 +480,9 @@ internal abstract class MapLogic
|
||||
FileHolder fileHolder;
|
||||
int? wholePercentages;
|
||||
const string lnk = ".lnk";
|
||||
ExifDirectory? exifDirectory;
|
||||
string personDisplayDirectoryName;
|
||||
const bool fromDistanceContent = true;
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories;
|
||||
List<(string File, int WholePercentages)>? wholePercentagesCollection;
|
||||
if (!mappedFile.FilePath.Name.EndsWith(lnk))
|
||||
{
|
||||
@ -518,14 +518,14 @@ internal abstract class MapLogic
|
||||
}
|
||||
dateOnly = DateOnly.FromDateTime(new DateTime(mappedFile.FilePath.CreationTicks));
|
||||
if (mappedFile.FilePath.Name.EndsWith(lnk) || (!configuration.DistanceMoveUnableToMatch && !configuration.DistanceRenameToMatch) || !File.Exists(mappedFile.FilePath.FullName))
|
||||
directories = new List<MetadataExtractor.Directory>();
|
||||
exifDirectory = null;
|
||||
else
|
||||
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mappedFile.FilePath.FullName);
|
||||
exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(mappedFile.FilePath);
|
||||
RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value);
|
||||
personDisplayDirectoryName = mappedFile.PersonDisplayDirectoryName is null ? configuration.MappingDefaultName : mappedFile.PersonDisplayDirectoryName;
|
||||
lock (locationContainers)
|
||||
locationContainers.Add(new(dateOnly,
|
||||
directories,
|
||||
exifDirectory,
|
||||
mappedFile.DirectoryNumber,
|
||||
personDisplayDirectoryName,
|
||||
mappedFile.FilePath,
|
||||
@ -537,7 +537,7 @@ internal abstract class MapLogic
|
||||
wholePercentages.Value));
|
||||
}
|
||||
|
||||
private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
private static void LookForPossibleDuplicates(Configuration configuration, ReadOnlyCollection<LocationContainer> locationContainers)
|
||||
{
|
||||
string key;
|
||||
float? percent;
|
||||
@ -547,7 +547,7 @@ internal abstract class MapLogic
|
||||
RectangleF? itemPercentagesRectangle;
|
||||
(FilePath FilePath, int WholePercentages) item;
|
||||
Dictionary<string, (FilePath, int)> distinct = [];
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
key = string.Concat(locationContainer.PersonKey, locationContainer.Id);
|
||||
if (distinct.TryGetValue(key, out item))
|
||||
@ -890,9 +890,9 @@ internal abstract class MapLogic
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<LocationContainer<MetadataExtractor.Directory>> GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records)
|
||||
internal static List<LocationContainer> GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records)
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>> results = [];
|
||||
List<LocationContainer> results = [];
|
||||
List<MappedFile> mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records);
|
||||
if (mappedFiles.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch))
|
||||
{
|
||||
@ -909,7 +909,7 @@ internal abstract class MapLogic
|
||||
}
|
||||
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory))
|
||||
{
|
||||
ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> locationContainers = new(results.OrderBy(l => l.DirectoryNumber).ToArray());
|
||||
ReadOnlyCollection<LocationContainer> locationContainers = new(results.OrderBy(l => l.DirectoryNumber).ToArray());
|
||||
LookForPossibleDuplicates(configuration, locationContainers);
|
||||
}
|
||||
return results;
|
||||
@ -1248,10 +1248,10 @@ internal abstract class MapLogic
|
||||
return new(results);
|
||||
}
|
||||
|
||||
internal static ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> ConvertLocationContainers(List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
internal static ReadOnlyDictionary<int, List<LocationContainer>> ConvertLocationContainers(List<LocationContainer> locationContainers)
|
||||
{
|
||||
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> results = [];
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
Dictionary<int, List<LocationContainer>> results = [];
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (!results.ContainsKey(locationContainer.Id))
|
||||
results.Add(locationContainer.Id, []);
|
||||
|
@ -35,9 +35,9 @@ public interface IMapLogic
|
||||
static List<(string, long)> GetJLinkDirectories(string genealogicalDataCommunicationFile, string[] jLinks, string personBirthdayFormat, char[] personCharacters, string a2PeopleSingletonDirectory, string a2PeopleContentDirectory) =>
|
||||
MapLogic.GetJLinkDirectories(genealogicalDataCommunicationFile, jLinks, personBirthdayFormat, personCharacters, a2PeopleSingletonDirectory, a2PeopleContentDirectory);
|
||||
|
||||
void TestStatic_SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer<MetadataExtractor.Directory>> locationContainers) =>
|
||||
void TestStatic_SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer> locationContainers) =>
|
||||
SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers);
|
||||
static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer<MetadataExtractor.Directory>> locationContainers) =>
|
||||
static void SetCreationTimeMaybeMoveToDecade(Property.Models.Configuration propertyConfiguration, bool moveToDecade, Shared.Models.MappingFromItem mappingFromItem, ReadOnlyCollection<Shared.Models.LocationContainer> locationContainers) =>
|
||||
DecadeLogic.SetCreationTimeMaybeMoveToDecade(propertyConfiguration, moveToDecade, mappingFromItem, locationContainers);
|
||||
|
||||
bool? TestStatic_CanReMap(long[] jLinkResolvedPersonKeys, ReadOnlyDictionary<int, ReadOnlyCollection<Shared.Models.PersonContainer>>? wholePercentagesToPersonContainers, Shared.Models.MappingFromLocation mappingFromLocation) =>
|
||||
|
@ -8,14 +8,14 @@ namespace View_by_Distance.Map.Models.Stateless;
|
||||
internal abstract class RelationLogic
|
||||
{
|
||||
|
||||
internal record Group(string Key, long PersonKey, ReadOnlyCollection<LocationContainer<MetadataExtractor.Directory>> RelationContainersCollection);
|
||||
internal record Group(string Key, long PersonKey, ReadOnlyCollection<LocationContainer> RelationContainersCollection);
|
||||
|
||||
private static Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> GetPersonKeyTo(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
private static Dictionary<long, Dictionary<int, List<LocationContainer>>> GetPersonKeyTo(Configuration configuration, List<LocationContainer> locationContainers)
|
||||
{
|
||||
List<LocationContainer<MetadataExtractor.Directory>>? collection;
|
||||
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>? yearTo;
|
||||
Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> personKeyTo = [];
|
||||
foreach (LocationContainer<MetadataExtractor.Directory> locationContainer in locationContainers)
|
||||
List<LocationContainer>? collection;
|
||||
Dictionary<int, List<LocationContainer>>? yearTo;
|
||||
Dictionary<long, Dictionary<int, List<LocationContainer>>> personKeyTo = [];
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (!locationContainer.FromDistanceContent)
|
||||
continue;
|
||||
@ -38,7 +38,7 @@ internal abstract class RelationLogic
|
||||
return personKeyTo;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<Group> GetGroups(Configuration configuration, List<LocationContainer<MetadataExtractor.Directory>> locationContainers)
|
||||
private static ReadOnlyCollection<Group> GetGroups(Configuration configuration, List<LocationContainer> locationContainers)
|
||||
{
|
||||
List<Group> results = [];
|
||||
string key;
|
||||
@ -46,10 +46,10 @@ internal abstract class RelationLogic
|
||||
List<int> years = [];
|
||||
List<int> indices = [];
|
||||
List<(int Index, int Year)> sort = [];
|
||||
List<LocationContainer<MetadataExtractor.Directory>> collection = [];
|
||||
KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValue;
|
||||
Dictionary<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> personKeyTo = GetPersonKeyTo(configuration, locationContainers);
|
||||
foreach (KeyValuePair<long, Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>>> keyValuePair in personKeyTo)
|
||||
List<LocationContainer> collection = [];
|
||||
KeyValuePair<int, List<LocationContainer>> keyValue;
|
||||
Dictionary<long, Dictionary<int, List<LocationContainer>>> personKeyTo = GetPersonKeyTo(configuration, locationContainers);
|
||||
foreach (KeyValuePair<long, Dictionary<int, List<LocationContainer>>> keyValuePair in personKeyTo)
|
||||
{
|
||||
sort.Clear();
|
||||
years.Clear();
|
||||
@ -403,7 +403,7 @@ internal abstract class RelationLogic
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance<MetadataExtractor.Directory> distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer<MetadataExtractor.Directory>> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
|
||||
internal static void SaveMappedRelations(Configuration configuration, Shared.Models.Methods.IDistance distance, string a2PeopleContentDirectory, string eDistanceContentDirectory, long ticks, List<LocationContainer> locationContainers, ReadOnlyDictionary<string, PersonContainer> readOnlyPersonKeyFormattedToPersonContainer, ReadOnlyDictionary<long, List<PersonContainer>> readOnlyPersonKeyToPersonContainerCollection)
|
||||
{
|
||||
int take;
|
||||
string directory;
|
||||
|
@ -42,6 +42,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Property\Property.csproj" />
|
||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -4,8 +4,8 @@ using Phares.Shared;
|
||||
using ShellProgressBar;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Metadata.Query.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
namespace View_by_Distance.Metadata.Query;
|
||||
@ -56,18 +56,18 @@ public class MetadataQuery
|
||||
{ }
|
||||
}
|
||||
|
||||
private List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks)
|
||||
private List<(string FileName, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks)
|
||||
{
|
||||
int count;
|
||||
string json;
|
||||
string message;
|
||||
string fileName;
|
||||
FileInfo fileInfo;
|
||||
FilePath filePath;
|
||||
FileHolder fileHolder;
|
||||
ProgressBar progressBar;
|
||||
ExifDirectory exifDirectory;
|
||||
const string fileSearchFilter = "*";
|
||||
const bool useCeilingAverage = true;
|
||||
const string directorySearchFilter = "*";
|
||||
Dictionary<string, List<KeyValuePair<string, string>>>? dictionary;
|
||||
List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> collection = [];
|
||||
List<(string FileName, string TagGroup, string TagIdName, string Value)> collection = [];
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
ReadOnlyCollection<string[]> filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter, useCeilingAverage);
|
||||
foreach (string[] files in filesCollection)
|
||||
@ -78,57 +78,33 @@ public class MetadataQuery
|
||||
progressBar = new(files.Length, message, options);
|
||||
foreach (string file in files)
|
||||
{
|
||||
count = 0;
|
||||
progressBar.Tick();
|
||||
json = File.ReadAllText(file);
|
||||
fileName = Path.GetFileName(file);
|
||||
dictionary = JsonSerializer.Deserialize<Dictionary<string, List<KeyValuePair<string, string>>>>(json);
|
||||
if (dictionary is null)
|
||||
continue;
|
||||
foreach (KeyValuePair<string, List<KeyValuePair<string, string>>> keyValuePair in dictionary)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
|
||||
count++;
|
||||
}
|
||||
foreach (KeyValuePair<string, List<KeyValuePair<string, string>>> keyValuePair in dictionary)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
|
||||
collection.Add(new(fileName, count.ToString("000000"), keyValuePair.Key, keyValue.Key, keyValue.Value));
|
||||
}
|
||||
fileInfo = new(file);
|
||||
fileHolder = FileHolder.Get(fileInfo);
|
||||
filePath = FilePath.Get(_PropertyConfiguration, fileHolder, index: null);
|
||||
exifDirectory = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePath);
|
||||
// exifDirectory.ExifDirectoryBase.Artist;
|
||||
// exifDirectory.ExifDirectoryBase.WinComment;
|
||||
// exifDirectory.ExifDirectoryBase.Model;
|
||||
// exifDirectory.ExifDirectoryBase.CameraOwnerName;
|
||||
// exifDirectory.ExifDirectoryBase.Make;
|
||||
// exifDirectory.ExifDirectoryBase.BodySerialNumber;
|
||||
// exifDirectory.ExifDirectoryBase.LensSerialNumber;
|
||||
// exifDirectory.ExifDirectoryBase.Software;
|
||||
// collection.Add(new(fileInfo.Name, keyValuePair.Key, keyValue.Key, keyValue.Value));
|
||||
}
|
||||
progressBar.Dispose();
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<string>> GetKeyValuePairs(List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> matches)
|
||||
{
|
||||
string key;
|
||||
string line;
|
||||
List<string>? valuePairs;
|
||||
Dictionary<string, List<string>> keyValuePairs = [];
|
||||
foreach ((string fileName, string count, string tagGroup, string tagIdName, string value) in matches)
|
||||
{
|
||||
key = $"{tagGroup}\t{tagIdName}\t{value.Trim()}";
|
||||
line = $"{tagGroup}\t{tagIdName}\t{value.Trim()}\t{count}\t{fileName}";
|
||||
if (!keyValuePairs.TryGetValue(key, out valuePairs))
|
||||
{
|
||||
keyValuePairs.Add(key, []);
|
||||
if (!keyValuePairs.TryGetValue(key, out valuePairs))
|
||||
throw new Exception();
|
||||
}
|
||||
valuePairs.Add(line);
|
||||
}
|
||||
return keyValuePairs;
|
||||
}
|
||||
|
||||
private void MetadataQueryFilesInDirectories(ILogger<Program>? logger, long ticks)
|
||||
{
|
||||
List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> collection = GetCollection(ticks);
|
||||
List<(string FileName, string TagGroup, string TagIdName, string Value)> collection = GetCollection(ticks);
|
||||
logger?.LogInformation($"Ready to query {collection.Count} entries?");
|
||||
IEnumerable<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> enumerable()
|
||||
IEnumerable<(string FileName, string TagGroup, string TagIdName, string Value)> enumerable()
|
||||
{
|
||||
foreach ((string FileName, string Count, string TagGroup, string TagIdName, string Value) l in collection)
|
||||
foreach ((string FileName, string TagGroup, string TagIdName, string Value) l in collection)
|
||||
{
|
||||
if (l.TagIdName.StartsWith("42016\t") && l.Value != "00000000000000000000000000000000")
|
||||
{
|
||||
@ -136,19 +112,18 @@ public class MetadataQuery
|
||||
}
|
||||
}
|
||||
}
|
||||
List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> matches = enumerable().ToList();
|
||||
List<(string FileName, string TagGroup, string TagIdName, string Value)> matches = enumerable().ToList();
|
||||
if (matches.Count != 0)
|
||||
{
|
||||
matches.Sort();
|
||||
StringBuilder stringBuilder = new();
|
||||
Dictionary<string, List<string>> keyValuePairs = GetKeyValuePairs(matches);
|
||||
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
||||
{
|
||||
if (keyValuePair.Value.Count != 2)
|
||||
continue;
|
||||
foreach (string line in keyValuePair.Value)
|
||||
_ = stringBuilder.AppendLine(line);
|
||||
}
|
||||
// foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
||||
// {
|
||||
// if (keyValuePair.Value.Count != 2)
|
||||
// continue;
|
||||
// foreach (string line in keyValuePair.Value)
|
||||
// _ = stringBuilder.AppendLine(line);
|
||||
// }
|
||||
string checkFile = $"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv";
|
||||
string text = stringBuilder.ToString();
|
||||
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, text, updateToWhenMatches: null, compareBeforeWrite: true, updateDateWhenMatches: false);
|
||||
|
@ -39,14 +39,13 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
|
||||
string result = JsonSerializer.Serialize(this, _WriteIndentedJsonSerializerOptions);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<string, MetadataExtractorDirectory> GetMetadataCollection(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem)
|
||||
public ExifDirectory GetMetadataCollection(FilePath filePath, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem)
|
||||
{
|
||||
Dictionary<string, MetadataExtractorDirectory>? results = null;
|
||||
string json = string.Empty;
|
||||
ExifDirectory? result = null;
|
||||
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
|
||||
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration, filePath);
|
||||
FileInfo fileInfo = new(Path.Combine(_FileGroups[_PropertyConfiguration.ResultSingleton][directoryIndex], $"{mappingFromItem.ImageFileHolder.NameWithoutExtension}{mappingFromItem.ImageFileHolder.ExtensionLowered}.json"));
|
||||
@ -61,34 +60,33 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
||||
fileInfo.Refresh();
|
||||
}
|
||||
if (_PropertiesChangedForMetadata)
|
||||
results = null;
|
||||
result = null;
|
||||
else if (!fileInfo.Exists)
|
||||
results = null;
|
||||
result = null;
|
||||
else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old"))
|
||||
throw new ArgumentException("must be a *.json file");
|
||||
else if (dateTimes.Count != 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
||||
results = null;
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
json = File.ReadAllText(fileInfo.FullName);
|
||||
string json = File.ReadAllText(fileInfo.FullName);
|
||||
try
|
||||
{
|
||||
results = Stateless.Methods.Metadata.Deserialize(json);
|
||||
if (results is null)
|
||||
result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
||||
if (result is null)
|
||||
throw new Exception();
|
||||
subFileTuples.Add(new Tuple<string, DateTime>(nameof(B_Metadata), fileInfo.LastWriteTime));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
results = null;
|
||||
result = null;
|
||||
parseExceptions.Add(nameof(B_Metadata));
|
||||
}
|
||||
}
|
||||
if (results is null || results.Count == 0)
|
||||
if (result is null)
|
||||
{
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(mappingFromItem.ImageFileHolder.FullName);
|
||||
results = Stateless.Methods.Metadata.GetKeyValuePairs(directories);
|
||||
json = JsonSerializer.Serialize(results, DictionaryStringMetadataExtractorDirectorySourceGenerationContext.Default.DictionaryStringMetadataExtractorDirectory);
|
||||
result = Stateless.Methods.IMetadata.GetExifDirectory(filePath);
|
||||
string json = JsonSerializer.Serialize(result, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
||||
bool updateDateWhenMatches = dateTimes.Count != 0 && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime;
|
||||
DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max();
|
||||
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime))
|
||||
@ -103,7 +101,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
||||
}
|
||||
}
|
||||
}
|
||||
return new(results);
|
||||
return result;
|
||||
}
|
||||
|
||||
(DateTime?, DateTime?[]) IMetadata<MetadataExtractor.Directory>.GetDateTimes(FileHolder fileHolder, IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
@ -203,7 +201,7 @@ public class B_Metadata : IMetadata<MetadataExtractor.Directory>
|
||||
}
|
||||
}
|
||||
}
|
||||
return new(result, results.ToArray());
|
||||
return new(result, [.. results]);
|
||||
}
|
||||
|
||||
}
|
@ -1,194 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models;
|
||||
|
||||
public record Exif(string? InteropIndex1,
|
||||
string? Noise37389,
|
||||
string? FocalPlaneXResolutionTiffEp37390,
|
||||
string? FocalPlaneYResolutionTiffEp37391,
|
||||
string? ImageNumber37393,
|
||||
string? SecurityClassification37394,
|
||||
string? ImageHistory37395,
|
||||
string? SubjectLocationTiffEp37396,
|
||||
string? ExposureIndexTiffEp37397,
|
||||
string? SpatialFreqResponseTiffEp37388,
|
||||
string? StandardIdTiffEp37398,
|
||||
string? UserComment37510,
|
||||
string? SubsecondTime37520,
|
||||
string? SubsecondTimeOriginal37521,
|
||||
string? SubsecondTimeDigitized37522,
|
||||
string? WinTitle40091,
|
||||
string? WinComment40092,
|
||||
string? WinAuthor40093,
|
||||
string? WinKeywords40094,
|
||||
string? Makernote37500,
|
||||
string? WinSubject40095,
|
||||
string? FlashEnergyTiffEp37387,
|
||||
string? Flash37385,
|
||||
string? IsoSpeedLatitudeYYY34868,
|
||||
string? IsoSpeedLatitudeZZZ34869,
|
||||
string? ExifVersion36864,
|
||||
string? DateTimeOriginal36867,
|
||||
string? DateTimeDigitized36868,
|
||||
string? TimeZone36880,
|
||||
string? TimeZoneOriginal36881,
|
||||
string? TimeZoneDigitized36882,
|
||||
string? FocalLength37386,
|
||||
string? ComponentsConfiguration37121,
|
||||
string? ShutterSpeed37377,
|
||||
string? Aperture37378,
|
||||
string? BrightnessValue37379,
|
||||
string? ExposureBias37380,
|
||||
string? MaxAperture37381,
|
||||
string? SubjectDistance37382,
|
||||
string? MeteringMode37383,
|
||||
string? WhiteBalance37384,
|
||||
string? CompressedAverageBitsPerPixel37122,
|
||||
string? IsoSpeed34867,
|
||||
string? FlashpixVersion40960,
|
||||
string? ExifImageWidth40962,
|
||||
string? Sharpness41994,
|
||||
string? DeviceSettingDescription41995,
|
||||
string? SubjectDistanceRange41996,
|
||||
string? ImageUniqueId42016,
|
||||
string? CameraOwnerName42032,
|
||||
string? BodySerialNumber42033,
|
||||
string? LensSpecification42034,
|
||||
string? LensMake42035,
|
||||
string? Saturation41993,
|
||||
string? LensModel42036,
|
||||
string? GdalMetadata42112,
|
||||
string? GdalNoData42113,
|
||||
string? Gamma42240,
|
||||
string? PrintImageMatchingInfo50341,
|
||||
string? PanasonicTitle50898,
|
||||
string? PanasonicTitle250899,
|
||||
string? Padding59932,
|
||||
string? Lens65002,
|
||||
string? LensSerialNumber42037,
|
||||
string? ColorSpace40961,
|
||||
string? Contrast41992,
|
||||
string? SceneCaptureType41990,
|
||||
string? ExifImageHeight40963,
|
||||
string? RelatedSoundFile40964,
|
||||
string? FlashEnergy41483,
|
||||
string? SpatialFreqResponse41484,
|
||||
string? FocalPlaneXResolution41486,
|
||||
string? FocalPlaneYResolution41487,
|
||||
string? FocalPlaneResolutionUnit41488,
|
||||
string? SubjectLocation41492,
|
||||
string? GainControl41991,
|
||||
string? ExposureIndex41493,
|
||||
string? FileSource41728,
|
||||
string? SceneType41729,
|
||||
string? CfaPattern41730,
|
||||
string? CustomRendered41985,
|
||||
string? ExposureMode41986,
|
||||
string? WhiteBalanceMode41987,
|
||||
string? DigitalZoomRatio41988,
|
||||
string? Film35MMEquivFocalLength41989,
|
||||
string? SensingMethod41495,
|
||||
string? RecommendedExposureIndex34866,
|
||||
string? StandardOutputSensitivity34865,
|
||||
string? SensitivityType34864,
|
||||
string? YResolution283,
|
||||
string? PlanarConfiguration284,
|
||||
string? PageName285,
|
||||
string? ResolutionUnit296,
|
||||
string? PageNumber297,
|
||||
string? TransferFunction301,
|
||||
string? Software305,
|
||||
string? DateTime306,
|
||||
string? XResolution282,
|
||||
string? Artist315,
|
||||
string? Predictor317,
|
||||
string? WhitePoint318,
|
||||
string? PrimaryChromaticities319,
|
||||
string? TileWidth322,
|
||||
string? TileLength323,
|
||||
string? TileOffsets324,
|
||||
string? TileByteCounts325,
|
||||
string? SubIfdOffset330,
|
||||
string? HostComputer316,
|
||||
string? ExtraSamples338,
|
||||
string? MaxSampleValue281,
|
||||
string? StripByteCounts279,
|
||||
string? InteropVersion2,
|
||||
string? NewSubfileType254,
|
||||
string? SubfileType255,
|
||||
string? ImageWidth256,
|
||||
string? ImageHeight257,
|
||||
string? BitsPerSample258,
|
||||
string? Compression259,
|
||||
string? PhotometricInterpretation262,
|
||||
string? MinSampleValue280,
|
||||
string? Thresholding263,
|
||||
string? DocumentName269,
|
||||
string? ImageDescription270,
|
||||
string? Make271,
|
||||
string? Model272,
|
||||
string? StripOffsets273,
|
||||
string? Orientation274,
|
||||
string? SamplesPerPixel277,
|
||||
string? RowsPerStrip278,
|
||||
string? FillOrder266,
|
||||
string? SampleFormat339,
|
||||
string? TransferRange342,
|
||||
string? JpegTables347,
|
||||
string? FNumber33437,
|
||||
string? PixelScale33550,
|
||||
string? IptcNaa33723,
|
||||
string? ModelTiePoint33922,
|
||||
string? PhotoshopSettings34377,
|
||||
string? InterColorProfile34675,
|
||||
string? GeoTiffGeoKeys34735,
|
||||
string? GeoTiffGeoDoubleParams34736,
|
||||
string? ExposureTime33434,
|
||||
string? GeoTiffGeoAsciiParams34737,
|
||||
string? SpectralSensitivity34852,
|
||||
string? IsoEquivalent34855,
|
||||
string? OptoElectricConversionFunction34856,
|
||||
string? Interlace34857,
|
||||
string? TimeZoneOffsetTiffEp34858,
|
||||
string? SelfTimerModeTiffEp34859,
|
||||
string? TimeZoneOffset34858,
|
||||
string? SelfTimerMode34859,
|
||||
string? ExposureProgram34850,
|
||||
string? Copyright33432,
|
||||
string? BatteryLevel33423,
|
||||
string? CfaPattern233422,
|
||||
string? JpegProc512,
|
||||
string? JpegRestartInterval515,
|
||||
string? JpegLosslessPredictors517,
|
||||
string? JpegPointTransforms518,
|
||||
string? JpegQTables519,
|
||||
string? JpegDcTables520,
|
||||
string? JpegAcTables521,
|
||||
string? YCbCrCoefficients529,
|
||||
string? YCbCrSubsampling530,
|
||||
string? YCbCrPositioning531,
|
||||
string? ReferenceBlackWhite532,
|
||||
string? StripRowCounts559,
|
||||
string? ApplicationNotes700,
|
||||
string? RelatedImageFileFormat4096,
|
||||
string? RelatedImageWidth4097,
|
||||
string? RelatedImageHeight4098,
|
||||
string? Rating18246,
|
||||
string? RatingPercent18249,
|
||||
string? CfaRepeatPatternDim33421)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, ExifSourceGenerationContext.Default.Exif);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Exif))]
|
||||
public partial class ExifSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models;
|
||||
|
||||
public record MetadataExtractorDirectory(string Name,
|
||||
bool HasError,
|
||||
ReadOnlyCollection<string> Errors,
|
||||
ReadOnlyDictionary<int, MetadataExtractorTag> Tags)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, MetadataExtractorDirectorySourceGenerationContext.Default.MetadataExtractorDirectory);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(MetadataExtractorDirectory))]
|
||||
public partial class MetadataExtractorDirectorySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(List<MetadataExtractorDirectory>))]
|
||||
public partial class MetadataExtractorDirectoryCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Dictionary<string, MetadataExtractorDirectory>))]
|
||||
public partial class DictionaryStringMetadataExtractorDirectorySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(ReadOnlyDictionary<string, MetadataExtractorDirectory>))]
|
||||
public partial class ReadOnlyDictionaryStringMetadataExtractorDirectorySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models;
|
||||
|
||||
public record MetadataExtractorTag(int Type,
|
||||
string? Description,
|
||||
bool HasName,
|
||||
string Name)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, MetadataExtractorTagSourceGenerationContext.Default.MetadataExtractorTag);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(MetadataExtractorTag))]
|
||||
public partial class MetadataExtractorTagSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(List<MetadataExtractorTag>))]
|
||||
public partial class MetadataExtractorTagCollectionSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Dictionary<string, MetadataExtractorTag>))]
|
||||
public partial class DictionaryStringMetadataExtractorTagSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(ReadOnlyDictionary<string, MetadataExtractorTag>))]
|
||||
public partial class ReadOnlyDictionaryStringMetadataExtractorTagSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
internal record Record(string Name,
|
||||
bool HasError,
|
||||
List<string> Errors,
|
||||
Dictionary<int, MetadataExtractorTag> Tags)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, RecordSourceGenerationContext.Default.Record);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(Record))]
|
||||
internal partial class RecordSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
54
Metadata/Models/Stateless/Base.cs
Normal file
54
Metadata/Models/Stateless/Base.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
internal static class Base
|
||||
{
|
||||
|
||||
internal static string GetMaker(ExifDirectoryBase[]? exifBaseDirectories)
|
||||
{
|
||||
string? result = null;
|
||||
if (exifBaseDirectories is not null)
|
||||
{
|
||||
string value;
|
||||
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
|
||||
{
|
||||
value = exifDirectoryBase?.Make is null ? string.Empty : exifDirectoryBase.Make.ToString().Trim();
|
||||
if (string.IsNullOrEmpty(value))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
result = $"{value[0].ToString().ToUpper()}{value[1..].ToLower()}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(result))
|
||||
result = "Unknown";
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetModel(ExifDirectoryBase[]? exifBaseDirectories)
|
||||
{
|
||||
string? result = null;
|
||||
if (exifBaseDirectories is not null)
|
||||
{
|
||||
string value;
|
||||
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
|
||||
{
|
||||
value = exifDirectoryBase?.Model is null ? string.Empty : exifDirectoryBase.Model.ToString().Trim();
|
||||
if (string.IsNullOrEmpty(value))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
result = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(result))
|
||||
result = "Unknown";
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
126
Metadata/Models/Stateless/Dimensions.cs
Normal file
126
Metadata/Models/Stateless/Dimensions.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
internal static class Dimensions
|
||||
{
|
||||
|
||||
#pragma warning disable IDE0230
|
||||
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||
{
|
||||
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
||||
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
||||
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||
};
|
||||
#pragma warning restore IDE0230
|
||||
|
||||
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
||||
{
|
||||
for (int i = 0; i < thatBytes.Length; i += 1)
|
||||
{
|
||||
if (thisBytes[i] == thatBytes[i])
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static short ReadLittleEndianInt16(BinaryReader binaryReader)
|
||||
{
|
||||
byte[] bytes = new byte[sizeof(short)];
|
||||
for (int i = 0; i < sizeof(short); i += 1)
|
||||
bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
|
||||
return BitConverter.ToInt16(bytes, 0);
|
||||
}
|
||||
|
||||
private static int ReadLittleEndianInt32(BinaryReader binaryReader)
|
||||
{
|
||||
byte[] bytes = new byte[sizeof(int)];
|
||||
for (int i = 0; i < sizeof(int); i += 1)
|
||||
bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
|
||||
return BitConverter.ToInt32(bytes, 0);
|
||||
}
|
||||
|
||||
private static Size? DecodeBitmap(BinaryReader binaryReader)
|
||||
{
|
||||
_ = binaryReader.ReadBytes(16);
|
||||
int width = binaryReader.ReadInt32();
|
||||
int height = binaryReader.ReadInt32();
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
private static Size? DecodeGif(BinaryReader binaryReader)
|
||||
{
|
||||
int width = binaryReader.ReadInt16();
|
||||
int height = binaryReader.ReadInt16();
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
private static Size? DecodePng(BinaryReader binaryReader)
|
||||
{
|
||||
_ = binaryReader.ReadBytes(8);
|
||||
int width = ReadLittleEndianInt32(binaryReader);
|
||||
int height = ReadLittleEndianInt32(binaryReader);
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
private static Size? DecodeJfif(BinaryReader binaryReader)
|
||||
{
|
||||
while (binaryReader.ReadByte() == 0xff)
|
||||
{
|
||||
byte marker = binaryReader.ReadByte();
|
||||
short chunkLength = ReadLittleEndianInt16(binaryReader);
|
||||
if (marker == 0xc0)
|
||||
{
|
||||
_ = binaryReader.ReadByte();
|
||||
int height = ReadLittleEndianInt16(binaryReader);
|
||||
int width = ReadLittleEndianInt16(binaryReader);
|
||||
return new Size(width, height);
|
||||
}
|
||||
if (chunkLength >= 0)
|
||||
_ = binaryReader.ReadBytes(chunkLength - 2);
|
||||
else
|
||||
{
|
||||
ushort uChunkLength = (ushort)chunkLength;
|
||||
_ = binaryReader.ReadBytes(uChunkLength - 2);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Size? DecodeWebP(BinaryReader binaryReader)
|
||||
{
|
||||
_ = binaryReader.ReadUInt32(); // Size
|
||||
_ = binaryReader.ReadBytes(15); // WEBP, VP8 + more
|
||||
_ = binaryReader.ReadBytes(3); // SYNC
|
||||
int width = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits width
|
||||
int height = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits height
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
internal static Size? GetDimensions(BinaryReader binaryReader)
|
||||
{
|
||||
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
|
||||
byte[] magicBytes = new byte[maxMagicBytesLength];
|
||||
for (int i = 0; i < maxMagicBytesLength; i += 1)
|
||||
{
|
||||
magicBytes[i] = binaryReader.ReadByte();
|
||||
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
||||
{
|
||||
if (StartsWith(magicBytes, kvPair.Key))
|
||||
return kvPair.Value(binaryReader);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static Size? GetDimensions(string path)
|
||||
{
|
||||
using BinaryReader binaryReader = new(File.OpenRead(path));
|
||||
return GetDimensions(binaryReader);
|
||||
}
|
||||
|
||||
}
|
529
Metadata/Models/Stateless/Exif.cs
Normal file
529
Metadata/Models/Stateless/Exif.cs
Normal file
@ -0,0 +1,529 @@
|
||||
using MetadataExtractor;
|
||||
using MetadataExtractor.Formats.Exif;
|
||||
using MetadataExtractor.Formats.Exif.Makernotes;
|
||||
using System.Globalization;
|
||||
using View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
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[] GetAviDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.AviDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.Avi.AviDirectory> aviDirectories = directories.OfType<MetadataExtractor.Formats.Avi.AviDirectory>();
|
||||
foreach (MetadataExtractor.Formats.Avi.AviDirectory aviDirectory in aviDirectories)
|
||||
{
|
||||
if (aviDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
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));
|
||||
if (dateTimeOriginal is null && duration is null && height is null && width is null)
|
||||
continue;
|
||||
results.Add(new(dateTimeOriginal, duration, height, width));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.ExifDirectoryBase[] GetExifBaseDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.ExifDirectoryBase> results = [];
|
||||
IEnumerable<ExifDirectoryBase> exifBaseDirectories = directories.OfType<ExifDirectoryBase>();
|
||||
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
|
||||
{
|
||||
if (exifDirectoryBase.Tags.Count == 0)
|
||||
continue;
|
||||
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));
|
||||
if (userComment is not null && userComment.Length > 255)
|
||||
userComment = "...";
|
||||
if (aperture is null
|
||||
&& applicationNotes is null
|
||||
&& artist is null
|
||||
&& bitsPerSample is null
|
||||
&& bodySerialNumber is null
|
||||
&& cameraOwnerName is null
|
||||
&& compressedAverageBitsPerPixel is null
|
||||
&& compression is null
|
||||
&& copyright is null
|
||||
&& dateTime is null
|
||||
&& dateTimeDigitized is null
|
||||
&& dateTimeOriginal is null
|
||||
&& documentName is null
|
||||
&& exifVersion is null
|
||||
&& exposureTime is null
|
||||
&& fileSource is null
|
||||
&& imageDescription is null
|
||||
&& imageHeight is null
|
||||
&& imageNumber is null
|
||||
&& imageUniqueId is null
|
||||
&& imageWidth is null
|
||||
&& isoSpeed is null
|
||||
&& lensMake is null
|
||||
&& lensModel is null
|
||||
&& lensSerialNumber is null
|
||||
&& make is null
|
||||
&& makerNote is null
|
||||
&& model is null
|
||||
&& orientation is null
|
||||
&& orientationValue is null
|
||||
&& rating is null
|
||||
&& ratingPercent is null
|
||||
&& securityClassification is null
|
||||
&& shutterSpeed is null
|
||||
&& software is null
|
||||
&& timeZone is null
|
||||
&& timeZoneDigitized is null
|
||||
&& timeZoneOriginal is null
|
||||
&& userComment is null
|
||||
&& winAuthor is null
|
||||
&& winComment is null
|
||||
&& winKeywords is null
|
||||
&& winSubject is null
|
||||
&& winTitle is null
|
||||
&& xResolution is not null
|
||||
&& yResolution is null)
|
||||
continue;
|
||||
results.Add(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 results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.FileMetadataDirectory[] GetFileMetadataDirectories(string file, IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.FileMetadataDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory> fileMetadataDirectories = directories.OfType<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory>();
|
||||
foreach (MetadataExtractor.Formats.FileSystem.FileMetadataDirectory fileMetadataDirectory in fileMetadataDirectories)
|
||||
{
|
||||
if (fileMetadataDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
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})");
|
||||
if (fileModifiedDate is null && fileName is null && fileSize is null)
|
||||
continue;
|
||||
results.Add(new(fileModifiedDate, fileName, fileSize));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.GifHeaderDirectory[] GetGifHeaderDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.GifHeaderDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.Gif.GifHeaderDirectory> gifHeaderDirectories = directories.OfType<MetadataExtractor.Formats.Gif.GifHeaderDirectory>();
|
||||
foreach (MetadataExtractor.Formats.Gif.GifHeaderDirectory gifHeaderDirectory in gifHeaderDirectories)
|
||||
{
|
||||
if (gifHeaderDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? imageHeight = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageHeight);
|
||||
string? imageWidth = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth);
|
||||
if (imageHeight is null && imageWidth is null)
|
||||
continue;
|
||||
results.Add(new(imageHeight, imageWidth));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.GpsDirectory[] GetGpsDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.GpsDirectory> results = [];
|
||||
IEnumerable<GpsDirectory> gpsDirectories = directories.OfType<GpsDirectory>();
|
||||
foreach (GpsDirectory gpsDirectory in gpsDirectories)
|
||||
{
|
||||
if (gpsDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
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));
|
||||
if (altitude is null && latitude is null && latitudeRef is null && longitude is null && longitudeRef is null && timeStamp is null)
|
||||
continue;
|
||||
results.Add(new(altitude,
|
||||
latitude,
|
||||
latitudeRef,
|
||||
longitude,
|
||||
longitudeRef,
|
||||
timeStamp));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.JpegDirectory[] GetJpegDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.JpegDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.Jpeg.JpegDirectory> jpegDirectories = directories.OfType<MetadataExtractor.Formats.Jpeg.JpegDirectory>();
|
||||
foreach (MetadataExtractor.Formats.Jpeg.JpegDirectory jpegDirectory in jpegDirectories)
|
||||
{
|
||||
if (jpegDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? imageHeight = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageHeight);
|
||||
string? imageWidth = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth);
|
||||
if (imageHeight is null && imageWidth is null)
|
||||
continue;
|
||||
results.Add(new(imageHeight, imageWidth));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.MakernoteDirectory[] GetMakernoteDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.MakernoteDirectory> results = [];
|
||||
IEnumerable<AppleMakernoteDirectory> appleMakernoteDirectories = directories.OfType<AppleMakernoteDirectory>();
|
||||
foreach (AppleMakernoteDirectory appleMakernoteDirectory in appleMakernoteDirectories)
|
||||
{
|
||||
if (appleMakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = null;
|
||||
string? firmwareVersion = null;
|
||||
string? qualityAndFileFormat = null;
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<CanonMakernoteDirectory> canonMakernoteDirectories = directories.OfType<CanonMakernoteDirectory>();
|
||||
foreach (CanonMakernoteDirectory canonMakernoteDirectory in canonMakernoteDirectories)
|
||||
{
|
||||
if (canonMakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagModelId);
|
||||
string? firmwareVersion = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagCanonFirmwareVersion);
|
||||
string? qualityAndFileFormat = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.CameraSettings.TagQuality);
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<NikonType2MakernoteDirectory> nikonType2MakernoteDirectories = directories.OfType<NikonType2MakernoteDirectory>();
|
||||
foreach (NikonType2MakernoteDirectory nikonType2MakernoteDirectory in nikonType2MakernoteDirectories)
|
||||
{
|
||||
if (nikonType2MakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagCameraSerialNumber);
|
||||
string? firmwareVersion = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagFirmwareVersion);
|
||||
string? qualityAndFileFormat = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagQualityAndFileFormat);
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<OlympusMakernoteDirectory> olympusMakernoteDirectories = directories.OfType<OlympusMakernoteDirectory>();
|
||||
foreach (OlympusMakernoteDirectory olympusMakernoteDirectory in olympusMakernoteDirectories)
|
||||
{
|
||||
if (olympusMakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagSerialNumber1);
|
||||
string? firmwareVersion = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagBodyFirmwareVersion);
|
||||
string? qualityAndFileFormat = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagJpegQuality);
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<PanasonicMakernoteDirectory> panasonicMakernoteDirectories = directories.OfType<PanasonicMakernoteDirectory>();
|
||||
foreach (PanasonicMakernoteDirectory panasonicMakernoteDirectory in panasonicMakernoteDirectories)
|
||||
{
|
||||
if (panasonicMakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagInternalSerialNumber);
|
||||
string? firmwareVersion = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagFirmwareVersion);
|
||||
string? qualityAndFileFormat = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagQualityMode);
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<SamsungType2MakernoteDirectory> samsungType2MakernoteDirectories = directories.OfType<SamsungType2MakernoteDirectory>();
|
||||
foreach (SamsungType2MakernoteDirectory samsungType2MakernoteDirectory in samsungType2MakernoteDirectories)
|
||||
{
|
||||
if (samsungType2MakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagSerialNumber);
|
||||
string? firmwareVersion = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagFirmwareName);
|
||||
string? qualityAndFileFormat = null;
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
IEnumerable<SonyType6MakernoteDirectory> sonyType6MakernoteDirectories = directories.OfType<SonyType6MakernoteDirectory>();
|
||||
foreach (SonyType6MakernoteDirectory sonyType6MakernoteDirectory in sonyType6MakernoteDirectories)
|
||||
{
|
||||
if (sonyType6MakernoteDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? cameraSerialNumber = null;
|
||||
string? firmwareVersion = null;
|
||||
string? qualityAndFileFormat = null;
|
||||
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||
continue;
|
||||
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.PhotoshopDirectory[] GetPhotoshopDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.PhotoshopDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory> photoshopDirectories = directories.OfType<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory>();
|
||||
foreach (MetadataExtractor.Formats.Photoshop.PhotoshopDirectory photoshopDirectory in photoshopDirectories)
|
||||
{
|
||||
if (photoshopDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? jpegQuality = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagJpegQuality);
|
||||
string? url = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl);
|
||||
if (jpegQuality is null && url is null)
|
||||
continue;
|
||||
results.Add(new(jpegQuality, url));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.PngDirectory[] GetPngDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.PngDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.Png.PngDirectory> pngDirectories = directories.OfType<MetadataExtractor.Formats.Png.PngDirectory>();
|
||||
foreach (MetadataExtractor.Formats.Png.PngDirectory pngDirectory in pngDirectories)
|
||||
{
|
||||
if (pngDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? imageHeight = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageHeight);
|
||||
string? imageWidth = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageWidth);
|
||||
string? textualData = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagTextualData);
|
||||
if (imageHeight is null && imageWidth is null && textualData is null)
|
||||
continue;
|
||||
results.Add(new(imageHeight, imageWidth, textualData));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.QuickTimeMovieHeaderDirectory[] GetQuickTimeMovieHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.QuickTimeMovieHeaderDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory> quickTimeMovieHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory>();
|
||||
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory in quickTimeMovieHeaderDirectories)
|
||||
{
|
||||
if (quickTimeMovieHeaderDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
DateTime? created;
|
||||
if (quickTimeMovieHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated, out DateTime checkDateTime))
|
||||
created = checkDateTime;
|
||||
else
|
||||
created = GetDateTime(quickTimeMovieHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated));
|
||||
if (created is null)
|
||||
continue;
|
||||
results.Add(new(created));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.QuickTimeTrackHeaderDirectory[] GetQuickTimeTrackHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.QuickTimeTrackHeaderDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory> quickTimeTrackHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory>();
|
||||
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory in quickTimeTrackHeaderDirectories)
|
||||
{
|
||||
if (quickTimeTrackHeaderDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
DateTime? created;
|
||||
if (quickTimeTrackHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated, out DateTime checkDateTime))
|
||||
created = checkDateTime;
|
||||
else
|
||||
created = GetDateTime(quickTimeTrackHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated));
|
||||
if (created is null)
|
||||
continue;
|
||||
results.Add(new(created));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.WebPDirectory[] GetWebPDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
List<Shared.Models.WebPDirectory> results = [];
|
||||
IEnumerable<MetadataExtractor.Formats.WebP.WebPDirectory> webPDirectories = directories.OfType<MetadataExtractor.Formats.WebP.WebPDirectory>();
|
||||
foreach (MetadataExtractor.Formats.WebP.WebPDirectory webPDirectory in webPDirectories)
|
||||
{
|
||||
if (webPDirectory.Tags.Count == 0)
|
||||
continue;
|
||||
string? imageHeight = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageHeight);
|
||||
string? imageWidth = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth);
|
||||
if (imageHeight is null && imageWidth is null)
|
||||
continue;
|
||||
results.Add(new(imageHeight, imageWidth));
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
Shared.Models.ExifDirectory result;
|
||||
Shared.Models.AviDirectory[] aviDirectories = GetAviDirectories(directories);
|
||||
Shared.Models.GpsDirectory[] gpsDirectories = GetGpsDirectories(directories);
|
||||
Shared.Models.PngDirectory[] pngDirectories = GetPngDirectories(directories);
|
||||
Shared.Models.JpegDirectory[] jpegDirectories = GetJpegDirectories(directories);
|
||||
Shared.Models.WebPDirectory[] webPDirectories = GetWebPDirectories(directories);
|
||||
Shared.Models.ExifDirectoryBase[] exifBaseDirectories = GetExifBaseDirectories(directories);
|
||||
Shared.Models.GifHeaderDirectory[] gifHeaderDirectories = GetGifHeaderDirectories(directories);
|
||||
Shared.Models.MakernoteDirectory[] makernoteDirectories = GetMakernoteDirectories(directories);
|
||||
Shared.Models.PhotoshopDirectory[] photoshopDirectories = GetPhotoshopDirectories(directories);
|
||||
Shared.Models.FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(filePath.FullName, directories);
|
||||
Shared.Models.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories);
|
||||
Shared.Models.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories);
|
||||
result = new(aviDirectories,
|
||||
exifBaseDirectories,
|
||||
fileMetadataDirectories,
|
||||
gifHeaderDirectories,
|
||||
gpsDirectories,
|
||||
size?.Height,
|
||||
jpegDirectories,
|
||||
makernoteDirectories,
|
||||
filePath.Name,
|
||||
photoshopDirectories,
|
||||
pngDirectories,
|
||||
quickTimeMovieHeaderDirectories,
|
||||
quickTimeTrackHeaderDirectories,
|
||||
webPDirectories,
|
||||
size?.Width);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static Shared.Models.ExifDirectory GetExifDirectory(Shared.Models.FilePath filePath)
|
||||
{
|
||||
Shared.Models.ExifDirectory? result;
|
||||
System.Drawing.Size? size = Dimensions.GetDimensions(filePath.FullName);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(filePath.FullName);
|
||||
result = Covert(filePath, size, directories);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
42
Metadata/Models/Stateless/Face.cs
Normal file
42
Metadata/Models/Stateless/Face.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
internal static class Face
|
||||
{
|
||||
|
||||
internal static string? GetFaceEncoding(PngDirectory[]? pngDirectories)
|
||||
{
|
||||
string? result = null;
|
||||
if (pngDirectories is not null)
|
||||
{
|
||||
const string comment = "Comment:";
|
||||
foreach (PngDirectory pngDirectory in pngDirectories)
|
||||
{
|
||||
if (pngDirectory.TextualData is null || !pngDirectory.TextualData.StartsWith(comment))
|
||||
continue;
|
||||
result = pngDirectory.TextualData[comment.Length..];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string? GetOutputResolution(PngDirectory[]? pngDirectories)
|
||||
{
|
||||
string? result = null;
|
||||
if (pngDirectories is not null)
|
||||
{
|
||||
const string artist = "Artist:";
|
||||
foreach (PngDirectory pngDirectory in pngDirectories)
|
||||
{
|
||||
if (pngDirectory.TextualData is null || !pngDirectory.TextualData.StartsWith(artist))
|
||||
continue;
|
||||
result = pngDirectory.TextualData[artist.Length..];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
121
Metadata/Models/Stateless/GPS.cs
Normal file
121
Metadata/Models/Stateless/GPS.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using MetadataExtractor;
|
||||
using View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless;
|
||||
|
||||
internal abstract class GPS
|
||||
{
|
||||
|
||||
private static bool CoordinateValidatorValidate(double latitude, double longitude)
|
||||
{
|
||||
if (latitude is < (-90) or > 90)
|
||||
return false;
|
||||
if (longitude is < (-180) or > 180)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static double GetRadius(IMetadata.DistanceUnit distanceUnit)
|
||||
{
|
||||
return distanceUnit switch
|
||||
{
|
||||
IMetadata.DistanceUnit.Kilometers => 6371.0, // EarthRadiusInKilometers;
|
||||
IMetadata.DistanceUnit.Meters => 6371000.0, // EarthRadiusInMeters;
|
||||
IMetadata.DistanceUnit.NauticalMiles => 3440.0, // EarthRadiusInNauticalMiles;
|
||||
IMetadata.DistanceUnit.Miles => 3959.0, // EarthRadiusInMiles;
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
}
|
||||
|
||||
private static double ToRadian(double d) =>
|
||||
d * (Math.PI / 180);
|
||||
|
||||
private static double DiffRadian(double val1, double val2) =>
|
||||
ToRadian(val2) - ToRadian(val1);
|
||||
|
||||
internal static double GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, IMetadata.DistanceUnit distanceUnit = IMetadata.DistanceUnit.Miles)
|
||||
{
|
||||
if (!CoordinateValidatorValidate(originLatitude, originLongitude))
|
||||
throw new ArgumentException("Invalid origin coordinates supplied.");
|
||||
if (!CoordinateValidatorValidate(destinationLatitude, destinationLongitude))
|
||||
throw new ArgumentException("Invalid destination coordinates supplied.");
|
||||
double radius = GetRadius(distanceUnit);
|
||||
return Math.Round(
|
||||
radius * 2 *
|
||||
Math.Asin(Math.Min(1,
|
||||
Math.Sqrt(
|
||||
Math.Pow(Math.Sin(DiffRadian(originLatitude, destinationLatitude) / 2.0), 2.0) +
|
||||
Math.Cos(ToRadian(originLatitude)) * Math.Cos(ToRadian(destinationLatitude)) *
|
||||
Math.Pow(Math.Sin(DiffRadian(originLongitude, destinationLongitude) / 2.0),
|
||||
2.0)))), decimalPlaces);
|
||||
}
|
||||
|
||||
private static double ParseValueFromDmsString(string value)
|
||||
{
|
||||
double result;
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return double.MinValue;
|
||||
|
||||
double secondsValue;
|
||||
string[] degrees = value.Split('°');
|
||||
if (degrees.Length != 2)
|
||||
return double.MinValue;
|
||||
if (!double.TryParse(degrees[0], out double degreesValue))
|
||||
return double.MinValue;
|
||||
|
||||
string[] minutes = degrees[1].Split('\'');
|
||||
if (minutes.Length != 2)
|
||||
return double.MinValue;
|
||||
if (!double.TryParse(minutes[0], out double minutesValue))
|
||||
return double.MinValue;
|
||||
|
||||
string[] seconds = minutes[1].Split('"');
|
||||
if (seconds.Length != 2)
|
||||
secondsValue = 0;
|
||||
else
|
||||
{
|
||||
if (!double.TryParse(seconds[0], out secondsValue))
|
||||
return double.MinValue;
|
||||
}
|
||||
result = Math.Abs(degreesValue) + (minutesValue / 60) + (secondsValue / 3600);
|
||||
|
||||
if (degreesValue < 0)
|
||||
result *= -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static GeoLocation? GeoLocation(GpsDirectory[]? gpsDirectories)
|
||||
{
|
||||
GeoLocation? result = null;
|
||||
if (gpsDirectories is not null)
|
||||
{
|
||||
foreach (GpsDirectory gpsDirectory in gpsDirectories)
|
||||
{
|
||||
if (string.IsNullOrEmpty(gpsDirectory?.Latitude))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
string latitudeDMS = gpsDirectory.Latitude;
|
||||
double latitude = ParseValueFromDmsString(latitudeDMS);
|
||||
if (string.IsNullOrEmpty(gpsDirectory.Longitude))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
string longitudeDMS = gpsDirectory.Longitude;
|
||||
double longitude = ParseValueFromDmsString(longitudeDMS);
|
||||
result = new(latitude, longitude);
|
||||
string dms = result.ToDmsString();
|
||||
if ($"{latitudeDMS}, {longitudeDMS}" != dms)
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
if (result is not null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using MetadataExtractor;
|
||||
using System.Collections.ObjectModel;
|
||||
using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
@ -14,39 +14,54 @@ public interface IMetadata
|
||||
Meters
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<string, MetadataExtractorDirectory> TestStatic_GetKeyValuePairs(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetKeyValuePairs(directories);
|
||||
static ReadOnlyDictionary<string, MetadataExtractorDirectory> GetKeyValuePairs(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
new(Metadata.GetKeyValuePairs(directories));
|
||||
ExifDirectory TestStatic_GetExifDirectory(FilePath filePath) =>
|
||||
GetExifDirectory(filePath);
|
||||
static ExifDirectory GetExifDirectory(FilePath filePath) =>
|
||||
Exif.GetExifDirectory(filePath);
|
||||
|
||||
string? TestStatic_GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetModel(directories);
|
||||
static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetModel(directories);
|
||||
string TestStatic_GetMaker(ExifDirectory? exifDirectory) =>
|
||||
GetMaker(exifDirectory);
|
||||
static string GetMaker(ExifDirectory? exifDirectory) =>
|
||||
Base.GetMaker(exifDirectory?.ExifBaseDirectories);
|
||||
|
||||
string? TestStatic_GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetFaceEncoding(directories);
|
||||
static string? GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetFaceEncoding(directories);
|
||||
string TestStatic_GetModel(ExifDirectory? exifDirectory) =>
|
||||
GetModel(exifDirectory);
|
||||
static string GetModel(ExifDirectory? exifDirectory) =>
|
||||
Base.GetModel(exifDirectory?.ExifBaseDirectories);
|
||||
|
||||
string? TestStatic_GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GetOutputResolution(directories);
|
||||
static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GetOutputResolution(directories);
|
||||
string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) =>
|
||||
GetOutputResolution(exifDirectory);
|
||||
static string? GetOutputResolution(ExifDirectory? exifDirectory) =>
|
||||
Face.GetOutputResolution(exifDirectory?.PngDirectories);
|
||||
|
||||
GeoLocation? TestStatic_GeoLocation(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
GeoLocation(directories);
|
||||
static GeoLocation? GeoLocation(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
Metadata.GeoLocation(directories);
|
||||
string? TestStatic_GetFaceEncoding(ExifDirectory? exifDirectory) =>
|
||||
GetFaceEncoding(exifDirectory);
|
||||
static string? GetFaceEncoding(ExifDirectory? exifDirectory) =>
|
||||
Face.GetFaceEncoding(exifDirectory?.PngDirectories);
|
||||
|
||||
GeoLocation? TestStatic_GeoLocation(ReadOnlyDictionary<string, MetadataExtractorDirectory> metadataExtractorDirectories) =>
|
||||
GeoLocation(metadataExtractorDirectories);
|
||||
static GeoLocation? GeoLocation(ReadOnlyDictionary<string, MetadataExtractorDirectory> metadataExtractorDirectories) =>
|
||||
Metadata.GeoLocation(metadataExtractorDirectories);
|
||||
GeoLocation? TestStatic_GeoLocation(ExifDirectory? exifDirectory) =>
|
||||
GeoLocation(exifDirectory);
|
||||
static GeoLocation? GeoLocation(ExifDirectory? exifDirectory) =>
|
||||
GPS.GeoLocation(exifDirectory?.GpsDirectories);
|
||||
|
||||
double? TestStatic_GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>
|
||||
GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
|
||||
static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>
|
||||
Metadata.GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
|
||||
GPS.GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
|
||||
|
||||
// string? TestStatic_GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
// GetFaceEncoding(directories);
|
||||
// static string? GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
// Metadata.GetFaceEncoding(directories);
|
||||
|
||||
// string? TestStatic_GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
// GetOutputResolution(directories);
|
||||
// static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories) =>
|
||||
// Metadata.GetOutputResolution(directories);
|
||||
|
||||
// Dictionary<string, MetadataExtractorDirectory> TestStatic_GetMetadataCollection(FileInfo fileInfo, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions) =>
|
||||
// GetMetadataCollection(fileInfo, subFileTuples, parseExceptions);
|
||||
// static Dictionary<string, MetadataExtractorDirectory> GetMetadataCollection(FileInfo fileInfo, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions) =>
|
||||
// Metadata.GetMetadataCollection(fileInfo, subFileTuples, parseExceptions);
|
||||
|
||||
}
|
@ -1,229 +0,0 @@
|
||||
using MetadataExtractor;
|
||||
using MetadataExtractor.Formats.Exif;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.Json;
|
||||
using static View_by_Distance.Metadata.Models.Stateless.Methods.IMetadata;
|
||||
|
||||
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
|
||||
|
||||
internal partial class Metadata
|
||||
{
|
||||
|
||||
internal static Dictionary<string, MetadataExtractorDirectory> GetKeyValuePairs(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
Dictionary<string, MetadataExtractorDirectory> results = [];
|
||||
MetadataExtractorTag metadataExtractorTag;
|
||||
MetadataExtractorDirectory? metadataExtractorDirectory;
|
||||
Dictionary<int, MetadataExtractorTag> metadataExtractorTags;
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
metadataExtractorTags = [];
|
||||
if (results.TryGetValue(directory.Name, out metadataExtractorDirectory))
|
||||
continue;
|
||||
foreach (Tag tag in directory.Tags)
|
||||
{
|
||||
metadataExtractorTag = new(tag.Type, tag.Description, tag.HasName, tag.Name);
|
||||
metadataExtractorTags.Add(tag.Type, metadataExtractorTag);
|
||||
}
|
||||
metadataExtractorDirectory = new(directory.Name, directory.HasError, new(directory.Errors.ToArray()), new(metadataExtractorTags));
|
||||
results.Add(directory.Name, metadataExtractorDirectory);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static Dictionary<string, MetadataExtractorDirectory> Deserialize(string json)
|
||||
{
|
||||
Dictionary<string, MetadataExtractorDirectory> results = [];
|
||||
Record? record;
|
||||
MetadataExtractorDirectory metadataExtractorDirectory;
|
||||
Dictionary<string, JsonElement>? keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
|
||||
if (keyValuePairs is null)
|
||||
throw new NullReferenceException(nameof(keyValuePairs));
|
||||
foreach (KeyValuePair<string, JsonElement> keyValuePair in keyValuePairs)
|
||||
{
|
||||
record = JsonSerializer.Deserialize(keyValuePair.Value.ToString(), RecordSourceGenerationContext.Default.Record);
|
||||
if (record is null)
|
||||
throw new NullReferenceException(nameof(record));
|
||||
metadataExtractorDirectory = new(record.Name, record.HasError, new(record.Errors), new(record.Tags));
|
||||
results.Add(record.Name, metadataExtractorDirectory);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static string? GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
string? result;
|
||||
List<string> results = [];
|
||||
const string comment = "Comment: ";
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
if (directory.Name != "PNG-tEXt")
|
||||
continue;
|
||||
foreach (Tag tag in directory.Tags)
|
||||
{
|
||||
if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
|
||||
continue;
|
||||
if (!tag.Description.StartsWith(comment))
|
||||
continue;
|
||||
results.Add(tag.Description);
|
||||
}
|
||||
}
|
||||
result = results.Count != 0 ? results[0][comment.Length..] : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
string? result;
|
||||
List<string> results = [];
|
||||
const string artist = "Artist: ";
|
||||
foreach (MetadataExtractor.Directory directory in directories)
|
||||
{
|
||||
if (directory.Name != "PNG-tEXt")
|
||||
continue;
|
||||
foreach (Tag tag in directory.Tags)
|
||||
{
|
||||
if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
|
||||
continue;
|
||||
if (!tag.Description.StartsWith(artist))
|
||||
continue;
|
||||
results.Add(tag.Description);
|
||||
}
|
||||
}
|
||||
result = results.Count != 0 ? results[0][artist.Length..] : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
string? result;
|
||||
ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().FirstOrDefault();
|
||||
if (exifDirectoryBase is null)
|
||||
result = null;
|
||||
else
|
||||
result = exifDirectoryBase.GetString(ExifDirectoryBase.TagModel);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static GeoLocation? GeoLocation(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||
{
|
||||
GeoLocation? result;
|
||||
GpsDirectory? gpsDirectory = directories.OfType<GpsDirectory>().FirstOrDefault();
|
||||
if (gpsDirectory is null)
|
||||
result = null;
|
||||
else
|
||||
result = gpsDirectory.GetGeoLocation();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool CoordinateValidatorValidate(double latitude, double longitude)
|
||||
{
|
||||
if (latitude is < (-90) or > 90)
|
||||
return false;
|
||||
if (longitude is < (-180) or > 180)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static double GetRadius(DistanceUnit distanceUnit)
|
||||
{
|
||||
return distanceUnit switch
|
||||
{
|
||||
DistanceUnit.Kilometers => 6371.0, // EarthRadiusInKilometers;
|
||||
DistanceUnit.Meters => 6371000.0, // EarthRadiusInMeters;
|
||||
DistanceUnit.NauticalMiles => 3440.0, // EarthRadiusInNauticalMiles;
|
||||
DistanceUnit.Miles => 3959.0, // EarthRadiusInMiles;
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
}
|
||||
|
||||
private static double ToRadian(double d) =>
|
||||
d * (Math.PI / 180);
|
||||
|
||||
private static double DiffRadian(double val1, double val2) =>
|
||||
ToRadian(val2) - ToRadian(val1);
|
||||
|
||||
internal static double GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles)
|
||||
{
|
||||
if (!CoordinateValidatorValidate(originLatitude, originLongitude))
|
||||
throw new ArgumentException("Invalid origin coordinates supplied.");
|
||||
if (!CoordinateValidatorValidate(destinationLatitude, destinationLongitude))
|
||||
throw new ArgumentException("Invalid destination coordinates supplied.");
|
||||
double radius = GetRadius(distanceUnit);
|
||||
return Math.Round(
|
||||
radius * 2 *
|
||||
Math.Asin(Math.Min(1,
|
||||
Math.Sqrt(
|
||||
Math.Pow(Math.Sin(DiffRadian(originLatitude, destinationLatitude) / 2.0), 2.0) +
|
||||
Math.Cos(ToRadian(originLatitude)) * Math.Cos(ToRadian(destinationLatitude)) *
|
||||
Math.Pow(Math.Sin(DiffRadian(originLongitude, destinationLongitude) / 2.0),
|
||||
2.0)))), decimalPlaces);
|
||||
}
|
||||
|
||||
private static double ParseValueFromDmsString(string value)
|
||||
{
|
||||
double result;
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return double.MinValue;
|
||||
|
||||
double secondsValue;
|
||||
string[] degrees = value.Split('°');
|
||||
if (degrees.Length != 2)
|
||||
return double.MinValue;
|
||||
if (!double.TryParse(degrees[0], out double degreesValue))
|
||||
return double.MinValue;
|
||||
|
||||
string[] minutes = degrees[1].Split('\'');
|
||||
if (minutes.Length != 2)
|
||||
return double.MinValue;
|
||||
if (!double.TryParse(minutes[0], out double minutesValue))
|
||||
return double.MinValue;
|
||||
|
||||
string[] seconds = minutes[1].Split('"');
|
||||
if (seconds.Length != 2)
|
||||
secondsValue = 0;
|
||||
else
|
||||
{
|
||||
if (!double.TryParse(seconds[0], out secondsValue))
|
||||
return double.MinValue;
|
||||
}
|
||||
result = Math.Abs(degreesValue) + (minutesValue / 60) + (secondsValue / 3600);
|
||||
|
||||
if (degreesValue < 0)
|
||||
result *= -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static GeoLocation? GeoLocation(ReadOnlyDictionary<string, MetadataExtractorDirectory> metadataExtractorDirectories)
|
||||
{
|
||||
GeoLocation? result;
|
||||
if (!metadataExtractorDirectories.TryGetValue("GPS", out MetadataExtractorDirectory? metadataExtractorDirectory))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
MetadataExtractorTag? metadataExtractorTag;
|
||||
if (!metadataExtractorDirectory.Tags.TryGetValue((int)Shared.Models.Stateless.IExif.Tags.GPSLatitude, out metadataExtractorTag) || string.IsNullOrEmpty(metadataExtractorTag.Description))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
string latitudeDMS = metadataExtractorTag.Description;
|
||||
double latitude = ParseValueFromDmsString(latitudeDMS);
|
||||
if (!metadataExtractorDirectory.Tags.TryGetValue((int)Shared.Models.Stateless.IExif.Tags.GPSLongitude, out metadataExtractorTag) || string.IsNullOrEmpty(metadataExtractorTag.Description))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
string longitudeDMS = metadataExtractorTag.Description;
|
||||
double longitude = ParseValueFromDmsString(longitudeDMS);
|
||||
result = new(latitude, longitude);
|
||||
string dms = result.ToDmsString();
|
||||
if ($"{latitudeDMS}, {longitudeDMS}" != dms)
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,6 @@ using System.Text;
|
||||
using View_by_Distance.Offset.Date.Time.Original.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Offset.Date.Time.Original;
|
||||
|
||||
@ -113,7 +112,7 @@ public class OffsetDateTimeOriginal
|
||||
string checkFile;
|
||||
PropertyItem? propertyItem;
|
||||
string? ticksDirectory = null;
|
||||
int dateTimeOriginal = (int)IExif.Tags.DateTimeOriginal;
|
||||
int dateTimeOriginal = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal;
|
||||
for (int i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
ticksDirectory = Path.Combine(sourceDirectory, ticks.ToString());
|
||||
|
@ -8,7 +8,6 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Property.Models.Stateless;
|
||||
|
||||
@ -207,13 +206,12 @@ internal partial class Property
|
||||
DateTime? dateTimeOriginal = null;
|
||||
DateTime? dateTimeDigitized = null;
|
||||
DateTime? dateTimeOriginalByLogic = null;
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories;
|
||||
DateTime? dateTimeFromName = GetDateTimeFromName(fileHolder);
|
||||
if (!isValidImageFormatExtension && fileHolder.Exists && metadata is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
|
||||
(dateTimeOriginalByLogic, DateTime?[] metadataDateTimes) = metadata.GetDateTimes(fileHolder, directories);
|
||||
dateTimesByLogic = GetDateTimes(metadataDateTimes);
|
||||
message = null;
|
||||
@ -244,9 +242,9 @@ internal partial class Property
|
||||
id ??= Shared.Models.Stateless.Methods.IId.GetDeterministicHashCode(bytes);
|
||||
}
|
||||
dateTimeFormat = IProperty.DateTimeFormat();
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime);
|
||||
if (propertyItem?.Value is not null)
|
||||
{
|
||||
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
@ -256,9 +254,9 @@ internal partial class Property
|
||||
dateTime = checkDateTime;
|
||||
}
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized);
|
||||
if (propertyItem?.Value is not null)
|
||||
{
|
||||
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
@ -268,9 +266,9 @@ internal partial class Property
|
||||
dateTimeDigitized = checkDateTime;
|
||||
}
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal);
|
||||
if (propertyItem?.Value is not null)
|
||||
{
|
||||
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
@ -280,9 +278,9 @@ internal partial class Property
|
||||
dateTimeOriginal = checkDateTime;
|
||||
}
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.GpsDirectory.TagDateStamp))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.GpsDirectory.TagDateStamp);
|
||||
if (propertyItem?.Value is not null)
|
||||
{
|
||||
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
@ -292,27 +290,27 @@ internal partial class Property
|
||||
gpsDateStamp = checkDateTime;
|
||||
}
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.Make))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagMake))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.Make);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagMake);
|
||||
if (propertyItem?.Value is not null)
|
||||
make = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.Model))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModel))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.Model);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModel);
|
||||
if (propertyItem?.Value is not null)
|
||||
model = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation);
|
||||
if (propertyItem?.Value is not null)
|
||||
orientation = BitConverter.ToInt16(propertyItem.Value, 0);
|
||||
}
|
||||
if (image.PropertyIdList.Contains((int)IExif.Tags.XPKeywords))
|
||||
if (image.PropertyIdList.Contains(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinKeywords))
|
||||
{
|
||||
propertyItem = image.GetPropertyItem((int)IExif.Tags.XPKeywords);
|
||||
propertyItem = image.GetPropertyItem(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinKeywords);
|
||||
if (propertyItem?.Value is not null)
|
||||
{
|
||||
if (propertyItem.Type == 2)
|
||||
@ -333,7 +331,7 @@ internal partial class Property
|
||||
{
|
||||
try
|
||||
{
|
||||
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
|
||||
(dateTimeOriginalByLogic, DateTime?[] metadataDateTimes) = metadata.GetDateTimes(fileHolder, directories);
|
||||
dateTimesByLogic = GetDateTimes(dateTimes, metadataDateTimes);
|
||||
message = null;
|
||||
|
@ -10,7 +10,6 @@ using View_by_Distance.Property.Models;
|
||||
using View_by_Distance.Property.Models.Stateless;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Properties;
|
||||
using View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
namespace View_by_Distance.Resize.Models;
|
||||
|
||||
@ -98,7 +97,7 @@ public class C_Resize
|
||||
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetGifLowQuality()
|
||||
{
|
||||
(ImageCodecInfo, EncoderParameters, string) result;
|
||||
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Gif;
|
||||
ImageFormat imageFormat = ImageFormat.Gif;
|
||||
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First();
|
||||
EncoderParameters encoderParameters = new(1);
|
||||
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
|
||||
@ -111,7 +110,7 @@ public class C_Resize
|
||||
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetPngLowQuality()
|
||||
{
|
||||
(ImageCodecInfo, EncoderParameters, string) result;
|
||||
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Png;
|
||||
ImageFormat imageFormat = ImageFormat.Png;
|
||||
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First();
|
||||
EncoderParameters encoderParameters = new(1);
|
||||
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
|
||||
@ -124,22 +123,22 @@ public class C_Resize
|
||||
public static (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) GetTuple(string outputExtension, int outputQuality)
|
||||
{
|
||||
(ImageCodecInfo, EncoderParameters, string) result;
|
||||
System.Drawing.Imaging.ImageFormat imageFormat = outputExtension switch
|
||||
ImageFormat imageFormat = outputExtension switch
|
||||
{
|
||||
".gif" => System.Drawing.Imaging.ImageFormat.Gif,
|
||||
".jfif" => System.Drawing.Imaging.ImageFormat.Jpeg,
|
||||
".jpe" => System.Drawing.Imaging.ImageFormat.Jpeg,
|
||||
".jpeg" => System.Drawing.Imaging.ImageFormat.Jpeg,
|
||||
".jpg" => System.Drawing.Imaging.ImageFormat.Jpeg,
|
||||
".png" => System.Drawing.Imaging.ImageFormat.Png,
|
||||
".tif" => System.Drawing.Imaging.ImageFormat.Tiff,
|
||||
".tiff" => System.Drawing.Imaging.ImageFormat.Tiff,
|
||||
".gif" => ImageFormat.Gif,
|
||||
".jfif" => ImageFormat.Jpeg,
|
||||
".jpe" => ImageFormat.Jpeg,
|
||||
".jpeg" => ImageFormat.Jpeg,
|
||||
".jpg" => ImageFormat.Jpeg,
|
||||
".png" => ImageFormat.Png,
|
||||
".tif" => ImageFormat.Tiff,
|
||||
".tiff" => ImageFormat.Tiff,
|
||||
_ => throw new Exception(),
|
||||
};
|
||||
ImageCodecInfo imageCodecInfo = (from l in ImageCodecInfo.GetImageEncoders() where l.FormatID == imageFormat.Guid select l).First();
|
||||
EncoderParameters encoderParameters = new(1);
|
||||
// encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(75L, Int32)) 'Default
|
||||
// encoderParameters.Param[0] = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(95L, Int32)) 'Paint
|
||||
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(75L, Int32)) 'Default
|
||||
// encoderParameters.Param[0] = New EncoderParameter(Encoder.Quality, CType(95L, Int32)) 'Paint
|
||||
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, outputQuality);
|
||||
if (string.IsNullOrEmpty(imageCodecInfo.FilenameExtension))
|
||||
throw new NullReferenceException(nameof(imageCodecInfo.FilenameExtension));
|
||||
@ -163,17 +162,17 @@ public class C_Resize
|
||||
private void CopyPropertyItems(byte[] bytes, PropertyItem[] propertyItems, Bitmap bitmap)
|
||||
{
|
||||
bool hasId = false;
|
||||
int id = (int)IExif.Tags.DateTimeDigitized;
|
||||
int imageWidth = (int)IExif.Tags.ImageWidth;
|
||||
int imageLength = (int)IExif.Tags.ImageLength;
|
||||
int orientation = (int)IExif.Tags.Orientation;
|
||||
int id = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized;
|
||||
int imageWidth = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageWidth;
|
||||
int imageHeight = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageHeight;
|
||||
int orientation = MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation;
|
||||
foreach (PropertyItem propertyItem in propertyItems)
|
||||
{
|
||||
if (propertyItem.Id == id)
|
||||
hasId = true;
|
||||
else if (propertyItem.Id == imageWidth)
|
||||
continue;
|
||||
else if (propertyItem.Id == imageLength)
|
||||
else if (propertyItem.Id == imageHeight)
|
||||
continue;
|
||||
else if (propertyItem.Id == orientation)
|
||||
continue;
|
||||
|
@ -3,20 +3,20 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record ExifDirectory(AviDirectory AviDirectory,
|
||||
ExifDirectoryBase ExifDirectoryBase,
|
||||
string File,
|
||||
FileMetadataDirectory FileMetadataDirectory,
|
||||
GifHeaderDirectory GifHeaderDirectory,
|
||||
GpsDirectory GpsDirectory,
|
||||
public record ExifDirectory(AviDirectory[] AviDirectories,
|
||||
ExifDirectoryBase[] ExifBaseDirectories,
|
||||
FileMetadataDirectory[] FileMetadataDirectories,
|
||||
GifHeaderDirectory[] GifHeaderDirectories,
|
||||
GpsDirectory[] GpsDirectories,
|
||||
int? Height,
|
||||
string JsonFile,
|
||||
JpegDirectory JpegDirectory,
|
||||
PhotoshopDirectory PhotoshopDirectory,
|
||||
PngDirectory PngDirectory,
|
||||
QuickTimeMovieHeaderDirectory QuickTimeMovieHeaderDirectory,
|
||||
QuickTimeTrackHeaderDirectory QuickTimeTrackHeaderDirectory,
|
||||
WebPDirectory WebPDirectory,
|
||||
JpegDirectory[] JpegDirectories,
|
||||
MakernoteDirectory[] MakernoteDirectories,
|
||||
string OriginalFileName,
|
||||
PhotoshopDirectory[] PhotoshopDirectories,
|
||||
PngDirectory[] PngDirectories,
|
||||
QuickTimeMovieHeaderDirectory[] QuickTimeMovieHeaderDirectories,
|
||||
QuickTimeTrackHeaderDirectory[] QuickTimeTrackHeaderDirectories,
|
||||
WebPDirectory[] WebPDirectories,
|
||||
int? Width)
|
||||
{
|
||||
|
||||
@ -28,7 +28,7 @@ public record ExifDirectory(AviDirectory AviDirectory,
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(ExifDirectory))]
|
||||
public partial class ExifDirectorySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
|
@ -2,8 +2,8 @@ using System.Drawing;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record LocationContainer<T>(DateOnly CreationDateOnly,
|
||||
IReadOnlyList<T> Directories,
|
||||
public record LocationContainer(DateOnly CreationDateOnly,
|
||||
ExifDirectory? ExifDirectory,
|
||||
int? DirectoryNumber,
|
||||
string DisplayDirectoryName,
|
||||
FilePath FilePath,
|
||||
|
23
Shared/Models/MakernoteDirectory.cs
Normal file
23
Shared/Models/MakernoteDirectory.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record MakernoteDirectory(string? CameraSerialNumber,
|
||||
string? FirmwareVersion,
|
||||
string? QualityAndFileFormat)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = JsonSerializer.Serialize(this, MakernoteDirectorySourceGenerationContext.Default.MakernoteDirectory);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(MakernoteDirectory))]
|
||||
public partial class MakernoteDirectorySourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
@ -2,9 +2,9 @@ using System.Collections.ObjectModel;
|
||||
|
||||
namespace View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
public interface IDistance<T>
|
||||
public interface IDistance
|
||||
{
|
||||
|
||||
ReadOnlyCollection<RelationContainer> GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer<T>> locationContainers);
|
||||
ReadOnlyCollection<RelationContainer> GetRelationContainers(int faceDistancePermyriad, int locationContainerDistanceTake, float locationContainerDistanceTolerance, ReadOnlyCollection<LocationContainer> locationContainers);
|
||||
|
||||
}
|
@ -4,7 +4,8 @@ using System.Text.Json.Serialization;
|
||||
namespace View_by_Distance.Shared.Models;
|
||||
|
||||
public record PngDirectory(string? ImageHeight,
|
||||
string? ImageWidth)
|
||||
string? ImageWidth,
|
||||
string? TextualData)
|
||||
{
|
||||
|
||||
public override string ToString()
|
||||
|
@ -1,148 +1,148 @@
|
||||
namespace View_by_Distance.Shared.Models.Stateless;
|
||||
// namespace View_by_Distance.Shared.Models.Stateless;
|
||||
|
||||
public interface IExif
|
||||
{
|
||||
// public interface IExif
|
||||
// {
|
||||
|
||||
enum Tags : ushort
|
||||
{
|
||||
GPSVersionID = 0,
|
||||
GPSLatitudeRef = 1,
|
||||
GPSLatitude = 2,
|
||||
GPSLongitudeRef = 3,
|
||||
GPSLongitude = 4,
|
||||
GPSAltitudeRef = 5,
|
||||
GPSAltitude = 6,
|
||||
GPSTimestamp = 7,
|
||||
GPSSatellites = 8,
|
||||
GPSStatus = 9,
|
||||
GPSMeasureMode = 10,
|
||||
GPSDOP = 11,
|
||||
GPSSpeedRef = 12,
|
||||
GPSSpeed = 13,
|
||||
GPSTrackRef = 14,
|
||||
GPSTrack = 15,
|
||||
GPSImgDirectionRef = 16,
|
||||
GPSImgDirection = 17,
|
||||
GPSMapDatum = 18,
|
||||
GPSDestLatitudeRef = 19,
|
||||
GPSDestLatitude = 20,
|
||||
GPSDestLongitudeRef = 21,
|
||||
GPSDestLongitude = 22,
|
||||
GPSDestBearingRef = 23,
|
||||
GPSDestBearing = 24,
|
||||
GPSDestDistanceRef = 25,
|
||||
GPSDestDistance = 26,
|
||||
GPSProcessingMethod = 27,
|
||||
GPSAreaInformation = 28,
|
||||
GPSDateStamp = 29,
|
||||
GPSDifferential = 30,
|
||||
GPSHPositioningError = 31,
|
||||
ImageWidth = 256,
|
||||
ImageLength = 257,
|
||||
BitsPerSample = 258,
|
||||
Compression = 259,
|
||||
PhotometricInterpretation = 262,
|
||||
ImageDescription = 270,
|
||||
Make = 271,
|
||||
Model = 272,
|
||||
StripOffsets = 273,
|
||||
Orientation = 274,
|
||||
SamplesPerPixel = 277,
|
||||
RowsPerStrip = 278,
|
||||
StripByteCounts = 279,
|
||||
XResolution = 282,
|
||||
YResolution = 283,
|
||||
PlanarConfiguration = 284,
|
||||
ResolutionUnit = 296,
|
||||
TransferFunction = 301,
|
||||
Software = 305,
|
||||
DateTime = 306,
|
||||
Artist = 315,
|
||||
WhitePoint = 318,
|
||||
PrimaryChromaticities = 319,
|
||||
JPEGInterchangeFormat = 513,
|
||||
JPEGInterchangeFormatLength = 514,
|
||||
YCbCrCoefficients = 529,
|
||||
YCbCrSubSampling = 530,
|
||||
YCbCrPositioning = 531,
|
||||
ReferenceBlackWhite = 532,
|
||||
Copyright = 33432,
|
||||
ExposureTime = 33434,
|
||||
FNumber = 33437,
|
||||
ExposureProgram = 34850,
|
||||
SpectralSensitivity = 34852,
|
||||
ISOSpeedRatings = 34855,
|
||||
#pragma warning disable CA1069
|
||||
PhotographicSensitivity = 34855,
|
||||
#pragma warning restore CA1069
|
||||
OECF = 34856,
|
||||
SensitivityType = 34864,
|
||||
StandardOutputSensitivity = 34865,
|
||||
RecommendedExposureIndex = 34866,
|
||||
ISOSpeed = 34867,
|
||||
ISOSpeedLatitudeyyy = 34868,
|
||||
ISOSpeedLatitudezzz = 34869,
|
||||
ExifVersion = 36864,
|
||||
DateTimeOriginal = 36867,
|
||||
DateTimeDigitized = 36868,
|
||||
ComponentsConfiguration = 37121,
|
||||
CompressedBitsPerPixel = 37122,
|
||||
ShutterSpeedValue = 37377,
|
||||
ApertureValue = 37378,
|
||||
BrightnessValue = 37379,
|
||||
ExposureBiasValue = 37380,
|
||||
MaxApertureValue = 37381,
|
||||
SubjectDistance = 37382,
|
||||
MeteringMode = 37383,
|
||||
LightSource = 37384,
|
||||
Flash = 37385,
|
||||
FocalLength = 37386,
|
||||
SubjectArea = 37396,
|
||||
MakerNote = 37500,
|
||||
UserComment = 37510,
|
||||
SubsecTime = 37520,
|
||||
SubsecTimeOriginal = 37521,
|
||||
SubsecTimeDigitized = 37522,
|
||||
XPTitle = 40091,
|
||||
XPComment = 40092,
|
||||
XPAuthor = 40093,
|
||||
XPKeywords = 40094,
|
||||
XPSubject = 40095,
|
||||
FlashpixVersion = 40960,
|
||||
ColorSpace = 40961,
|
||||
PixelXDimension = 40962,
|
||||
PixelYDimension = 40963,
|
||||
RelatedSoundFile = 40964,
|
||||
FlashEnergy = 41483,
|
||||
SpatialFrequencyResponse = 41484,
|
||||
FocalPlaneXResolution = 41486,
|
||||
FocalPlaneYResolution = 41487,
|
||||
FocalPlaneResolutionUnit = 41488,
|
||||
SubjectLocation = 41492,
|
||||
ExposureIndex = 41493,
|
||||
SensingMethod = 41495,
|
||||
FileSource = 41728,
|
||||
SceneType = 41729,
|
||||
CFAPattern = 41730,
|
||||
CustomRendered = 41985,
|
||||
ExposureMode = 41986,
|
||||
WhiteBalance = 41987,
|
||||
DigitalZoomRatio = 41988,
|
||||
FocalLengthIn35mmFilm = 41989,
|
||||
SceneCaptureType = 41990,
|
||||
GainControl = 41991,
|
||||
Contrast = 41992,
|
||||
Saturation = 41993,
|
||||
Sharpness = 41994,
|
||||
DeviceSettingDescription = 41995,
|
||||
SubjectDistanceRange = 41996,
|
||||
ImageUniqueID = 42016,
|
||||
CameraOwnerName = 42032,
|
||||
BodySerialNumber = 42033,
|
||||
LensSpecification = 42034,
|
||||
LensMake = 42035,
|
||||
LensModel = 42036,
|
||||
LensSerialNumber = 42037
|
||||
}
|
||||
// enum Tags : ushort
|
||||
// {
|
||||
// GPSVersionID = 0,
|
||||
// GPSLatitudeRef = 1,
|
||||
// GPSLatitude = 2,
|
||||
// GPSLongitudeRef = 3,
|
||||
// GPSLongitude = 4,
|
||||
// GPSAltitudeRef = 5,
|
||||
// GPSAltitude = 6,
|
||||
// GPSTimestamp = 7,
|
||||
// GPSSatellites = 8,
|
||||
// GPSStatus = 9,
|
||||
// GPSMeasureMode = 10,
|
||||
// GPSDOP = 11,
|
||||
// GPSSpeedRef = 12,
|
||||
// GPSSpeed = 13,
|
||||
// GPSTrackRef = 14,
|
||||
// GPSTrack = 15,
|
||||
// GPSImgDirectionRef = 16,
|
||||
// GPSImgDirection = 17,
|
||||
// GPSMapDatum = 18,
|
||||
// GPSDestLatitudeRef = 19,
|
||||
// GPSDestLatitude = 20,
|
||||
// GPSDestLongitudeRef = 21,
|
||||
// GPSDestLongitude = 22,
|
||||
// GPSDestBearingRef = 23,
|
||||
// GPSDestBearing = 24,
|
||||
// GPSDestDistanceRef = 25,
|
||||
// GPSDestDistance = 26,
|
||||
// GPSProcessingMethod = 27,
|
||||
// GPSAreaInformation = 28,
|
||||
// GPSDateStamp = 29,
|
||||
// GPSDifferential = 30,
|
||||
// GPSHPositioningError = 31,
|
||||
// ImageWidth = 256,
|
||||
// ImageLength = 257,
|
||||
// BitsPerSample = 258,
|
||||
// Compression = 259,
|
||||
// PhotometricInterpretation = 262,
|
||||
// ImageDescription = 270,
|
||||
// Make = 271,
|
||||
// Model = 272,
|
||||
// StripOffsets = 273,
|
||||
// Orientation = 274,
|
||||
// SamplesPerPixel = 277,
|
||||
// RowsPerStrip = 278,
|
||||
// StripByteCounts = 279,
|
||||
// XResolution = 282,
|
||||
// YResolution = 283,
|
||||
// PlanarConfiguration = 284,
|
||||
// ResolutionUnit = 296,
|
||||
// TransferFunction = 301,
|
||||
// Software = 305,
|
||||
// DateTime = 306,
|
||||
// Artist = 315,
|
||||
// WhitePoint = 318,
|
||||
// PrimaryChromaticities = 319,
|
||||
// JPEGInterchangeFormat = 513,
|
||||
// JPEGInterchangeFormatLength = 514,
|
||||
// YCbCrCoefficients = 529,
|
||||
// YCbCrSubSampling = 530,
|
||||
// YCbCrPositioning = 531,
|
||||
// ReferenceBlackWhite = 532,
|
||||
// Copyright = 33432,
|
||||
// ExposureTime = 33434,
|
||||
// FNumber = 33437,
|
||||
// ExposureProgram = 34850,
|
||||
// SpectralSensitivity = 34852,
|
||||
// ISOSpeedRatings = 34855,
|
||||
// #pragma warning disable CA1069
|
||||
// PhotographicSensitivity = 34855,
|
||||
// #pragma warning restore CA1069
|
||||
// OECF = 34856,
|
||||
// SensitivityType = 34864,
|
||||
// StandardOutputSensitivity = 34865,
|
||||
// RecommendedExposureIndex = 34866,
|
||||
// ISOSpeed = 34867,
|
||||
// ISOSpeedLatitudeyyy = 34868,
|
||||
// ISOSpeedLatitudezzz = 34869,
|
||||
// ExifVersion = 36864,
|
||||
// DateTimeOriginal = 36867,
|
||||
// DateTimeDigitized = 36868,
|
||||
// ComponentsConfiguration = 37121,
|
||||
// CompressedBitsPerPixel = 37122,
|
||||
// ShutterSpeedValue = 37377,
|
||||
// ApertureValue = 37378,
|
||||
// BrightnessValue = 37379,
|
||||
// ExposureBiasValue = 37380,
|
||||
// MaxApertureValue = 37381,
|
||||
// SubjectDistance = 37382,
|
||||
// MeteringMode = 37383,
|
||||
// LightSource = 37384,
|
||||
// Flash = 37385,
|
||||
// FocalLength = 37386,
|
||||
// SubjectArea = 37396,
|
||||
// MakerNote = 37500,
|
||||
// UserComment = 37510,
|
||||
// SubsecTime = 37520,
|
||||
// SubsecTimeOriginal = 37521,
|
||||
// SubsecTimeDigitized = 37522,
|
||||
// XPTitle = 40091,
|
||||
// XPComment = 40092,
|
||||
// XPAuthor = 40093,
|
||||
// XPKeywords = 40094,
|
||||
// XPSubject = 40095,
|
||||
// FlashpixVersion = 40960,
|
||||
// ColorSpace = 40961,
|
||||
// PixelXDimension = 40962,
|
||||
// PixelYDimension = 40963,
|
||||
// RelatedSoundFile = 40964,
|
||||
// FlashEnergy = 41483,
|
||||
// SpatialFrequencyResponse = 41484,
|
||||
// FocalPlaneXResolution = 41486,
|
||||
// FocalPlaneYResolution = 41487,
|
||||
// FocalPlaneResolutionUnit = 41488,
|
||||
// SubjectLocation = 41492,
|
||||
// ExposureIndex = 41493,
|
||||
// SensingMethod = 41495,
|
||||
// FileSource = 41728,
|
||||
// SceneType = 41729,
|
||||
// CFAPattern = 41730,
|
||||
// CustomRendered = 41985,
|
||||
// ExposureMode = 41986,
|
||||
// WhiteBalance = 41987,
|
||||
// DigitalZoomRatio = 41988,
|
||||
// FocalLengthIn35mmFilm = 41989,
|
||||
// SceneCaptureType = 41990,
|
||||
// GainControl = 41991,
|
||||
// Contrast = 41992,
|
||||
// Saturation = 41993,
|
||||
// Sharpness = 41994,
|
||||
// DeviceSettingDescription = 41995,
|
||||
// SubjectDistanceRange = 41996,
|
||||
// ImageUniqueID = 42016,
|
||||
// CameraOwnerName = 42032,
|
||||
// BodySerialNumber = 42033,
|
||||
// LensSpecification = 42034,
|
||||
// LensMake = 42035,
|
||||
// LensModel = 42036,
|
||||
// LensSerialNumber = 42037
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
@ -25,9 +25,9 @@ public interface ILocation
|
||||
static Models.Location? GetLocation(DatabaseFile databaseFile, Marker marker, Models.OutputResolution outputResolution) =>
|
||||
Location.GetLocation(databaseFile, marker, outputResolution);
|
||||
|
||||
List<Models.Location> TestStatic_GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
List<Models.Location> TestStatic_GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
|
||||
static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
static List<Models.Location> GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum) =>
|
||||
Location.GetLocations(locationContainers, faces, mappingFromPhotoPrismCollection, rectangleIntersectMinimum);
|
||||
|
||||
RectangleF? TestStatic_GetPercentagesRectangle(int locationDigits, int wholePercentages) =>
|
||||
|
@ -245,7 +245,7 @@ internal abstract class Location
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<Models.Location> GetLocations<T>(List<LocationContainer<T>> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
|
||||
internal static List<Models.Location> GetLocations(List<LocationContainer> locationContainers, List<Models.Face> faces, List<MappingFromPhotoPrism> mappingFromPhotoPrismCollection, float rectangleIntersectMinimum)
|
||||
{
|
||||
List<Models.Location> results = [];
|
||||
bool any;
|
||||
@ -266,7 +266,7 @@ internal abstract class Location
|
||||
outputResolution ??= face.OutputResolution;
|
||||
}
|
||||
int before = results.Count;
|
||||
foreach (LocationContainer<T> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (locationContainer.Location is null)
|
||||
continue;
|
||||
@ -289,7 +289,7 @@ internal abstract class Location
|
||||
location = GetLocation(mappingFromPhotoPrism.DatabaseFile, marker, prismRectangle.Value);
|
||||
if (location is null)
|
||||
break;
|
||||
foreach (LocationContainer<T> locationContainer in locationContainers)
|
||||
foreach (LocationContainer locationContainer in locationContainers)
|
||||
{
|
||||
if (any)
|
||||
continue;
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Phares.Shared;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
@ -183,10 +182,10 @@ public class UnitTestResize
|
||||
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
|
||||
string blurHash = blurHasher.Encode(resizedFileHolder);
|
||||
Assert.IsNotNull(blurHash);
|
||||
ReadOnlyDictionary<string, MetadataExtractorDirectory> metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
string json = JsonSerializer.Serialize(metadataExtractorDirectories, ReadOnlyDictionaryStringMetadataExtractorDirectorySourceGenerationContext.Default.ReadOnlyDictionaryStringMetadataExtractorDirectory);
|
||||
ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
|
||||
File.WriteAllText("../../../.json", json);
|
||||
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(metadataExtractorDirectories);
|
||||
MetadataExtractor.GeoLocation? geoLocation = Metadata.Models.Stateless.Methods.IMetadata.GeoLocation(exifDirectory);
|
||||
double? distance = geoLocation is null ? null : Metadata.Models.Stateless.Methods.IMetadata.GetDistance(1, 1, geoLocation.Latitude, geoLocation.Longitude);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Phares.Shared;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
@ -251,14 +250,13 @@ public class UnitTestFace
|
||||
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber, filePath.Id.Value);
|
||||
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
|
||||
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
|
||||
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(resizedFileHolder.FullName);
|
||||
Dictionary<string, int[]> outputResolutionToResize = resize.GetResizeKeyValuePairs(_PropertyConfiguration, cResultsFullGroupDirectory, item.FilePath, subFileTuples, parseExceptions, item.Property, mappingFromItem);
|
||||
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
|
||||
resize.SaveResizedSubfile(_PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
|
||||
string blurHash = blurHasher.Encode(resizedFileHolder);
|
||||
Assert.IsNotNull(blurHash);
|
||||
ReadOnlyDictionary<string, MetadataExtractorDirectory>? metadataExtractorDirectories = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
string json = JsonSerializer.Serialize(metadataExtractorDirectories, ReadOnlyDictionaryStringMetadataExtractorDirectorySourceGenerationContext.Default.ReadOnlyDictionaryStringMetadataExtractorDirectory);
|
||||
ExifDirectory exifDirectory = metadata.GetMetadataCollection(item.FilePath, subFileTuples, parseExceptions, changesFrom, mappingFromItem);
|
||||
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
|
||||
File.WriteAllText("../../../.json", json);
|
||||
Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName);
|
||||
Assert.IsNotNull(image);
|
||||
|
Loading…
x
Reference in New Issue
Block a user