10 Commits

Author SHA1 Message Date
ebc1cf49f5 xmp and json sidecar support 2025-07-26 18:21:35 -07:00
518af493a8 Made useable by Helpers 2025-07-20 08:31:03 -07:00
d67d423ef3 Parameter constructors 2025-07-19 09:46:19 -07:00
ba11c04f4a Pack and published 8.0.118.14728
Metadata alignment
2025-07-19 09:25:58 -07:00
05fb8685d9 Removed Rectangle from LocationContainer
mapped-ids-then-whole-percentages-to-location-container

save-extracted-face

save-extracted-java-script-object-notation
2025-07-06 10:45:59 -07:00
2c9b1a68c0 House Cleaning 2025-07-05 13:37:47 -07:00
8f7fd02ba8 Interface over passing ticks 2025-07-04 09:11:05 -07:00
93598255c0 Changed GetDimensions to handle a stream at the end and one exit 2025-06-29 08:33:58 -07:00
9a51d995cc validation-image-file 2025-04-20 14:16:03 -07:00
23256c8152 Alignment with Console 2025-04-06 15:45:10 -07:00
134 changed files with 1672 additions and 1186 deletions

View File

@ -1,19 +1,23 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShellProgressBar; using ShellProgressBar;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Drawing;
using View_by_Distance.Compare.Models; using View_by_Distance.Compare.Models;
using View_by_Distance.Distance.Models.Stateless; using View_by_Distance.Distance.Models.Stateless;
using View_by_Distance.Face.Models.Stateless; using View_by_Distance.Face.Models.Stateless;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.People.Models.Stateless; using View_by_Distance.People.Models.Stateless;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Compare; namespace View_by_Distance.Compare;
public partial class Compare : ICompare, IDisposable public partial class Compare : ICompare, IDisposable
{ {
public long Ticks { get; init; }
public int? CurrentTick => _ProgressBar?.CurrentTick;
private ProgressBar? _ProgressBar; private ProgressBar? _ProgressBar;
private readonly ProgressBarOptions _ProgressBarOptions; private readonly ProgressBarOptions _ProgressBarOptions;
@ -41,54 +45,56 @@ public partial class Compare : ICompare, IDisposable
if (console is null) if (console is null)
throw new NullReferenceException(nameof(console)); throw new NullReferenceException(nameof(console));
ICompare compare = this; ICompare compare = this;
long ticks = DateTime.Now.Ticks; Ticks = DateTime.Now.Ticks;
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; _ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
CompareWork(logger, appSettings, compare, ticks); CompareWork(logger, appSettings, compare);
} }
private void CompareWork(ILogger<Program>? logger, AppSettings appSettings, ICompare compare, long ticks) private void CompareWork(ILogger<Program>? logger, AppSettings appSettings, ICompare compare)
{ {
const int updated = 0; const int updated = 0;
DistanceLimits? distanceLimits; DistanceLimits? distanceLimits;
logger?.LogInformation("{Ticks}", ticks);
ReadOnlyCollection<LocationContainer> matrix; ReadOnlyCollection<LocationContainer> matrix;
logger?.LogInformation("{Ticks}", compare.Ticks);
ReadOnlyCollection<SaveContainer> saveContainers; ReadOnlyCollection<SaveContainer> saveContainers;
ReadOnlyCollection<ExifDirectory> exifDirectories; ReadOnlyCollection<ExifDirectory> exifDirectories;
ReadOnlyCollection<LocationContainer> preFiltered; ReadOnlyCollection<LocationContainer> preFiltered;
ReadOnlyCollection<LocationContainer> postFiltered; ReadOnlyCollection<LocationContainer> postFiltered;
ReadOnlyDictionary<string, LocationContainer> onlyOne; ReadOnlyDictionary<string, LocationContainer> onlyOne;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, ticks); bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, compare);
ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings); ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings);
ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding = GetMappedExifDirectoryWithEncoding(appSettings, compare, ticks, readOnlyCollections); ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer = GetMappedIdsThenWholePercentagesToLocationContainer(appSettings, compare, readOnlyCollections);
ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs = IDistance.Extract(appSettings.CompareSettings, mappedExifDirectoryWithEncoding); if (appSettings.CompareSettings.SaveExtractedFaces || appSettings.CompareSettings.SaveExtractedJavaScriptObjectNotation)
SaveExtracted(appSettings, mappedIdsThenWholePercentagesToLocationContainer);
foreach (string outputResolution in appSettings.CompareSettings.OutputResolutions) foreach (string outputResolution in appSettings.CompareSettings.OutputResolutions)
{ {
if (runToDoCollectionFirst || outputResolution.Any(char.IsNumber)) if (runToDoCollectionFirst || outputResolution.Any(char.IsNumber))
continue; continue;
_ProgressBar?.Dispose();
logger?.LogInformation("{outputResolution}", outputResolution); logger?.LogInformation("{outputResolution}", outputResolution);
exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution); exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, outputResolution);
preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories); preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, readOnlyCollections, mappedIdsThenWholePercentagesToLocationContainer, exifDirectories);
if (preFiltered.Count == 0) if (preFiltered.Count == 0)
continue; continue;
if (appSettings.CompareSettings.SaveExtractedFaces || appSettings.CompareSettings.SaveExtractedJavaScriptObjectNotation)
SaveExtracted(appSettings, preFiltered);
distanceLimits = new(appSettings.DistanceSettings); distanceLimits = new(appSettings.DistanceSettings);
postFiltered = IDistance.GetPostFilterLocationContainer(preFiltered, distanceLimits); postFiltered = IDistance.GetPostFilterLocationContainer(preFiltered, distanceLimits);
if (postFiltered.Count == 0) if (postFiltered.Count == 0)
continue; continue;
matrix = IDistance.GetMatrixLocationContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered); matrix = IDistance.GetMatrixLocationContainers(appSettings.DistanceSettings, compare, mappedIdsThenWholePercentagesToLocationContainer, distanceLimits, postFiltered);
if (matrix.Count == 0) if (matrix.Count == 0)
continue; continue;
onlyOne = IDistance.GetOnlyOne(appSettings.DistanceSettings, matrix); onlyOne = IDistance.GetOnlyOne(appSettings.DistanceSettings, matrix);
if (onlyOne.Count == 0) if (onlyOne.Count == 0)
continue; continue;
saveContainers = IDistance.GetSaveContainers(appSettings.ResultSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution, onlyOne); saveContainers = IDistance.GetSaveContainers(appSettings.ResultSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, outputResolution, onlyOne);
if (saveContainers.Count == 0) if (saveContainers.Count == 0)
continue; continue;
IDistance.SaveContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, updated, saveContainers); IDistance.SaveContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, updated, saveContainers);
} }
} }
private static bool GetRunToDoCollectionFirst(AppSettings appSettings, long ticks) private static bool GetRunToDoCollectionFirst(AppSettings appSettings, ICompare compare)
{ {
bool result = appSettings.DistanceSettings.SaveSortingWithoutPerson; bool result = appSettings.DistanceSettings.SaveSortingWithoutPerson;
if (!result) if (!result)
@ -103,7 +109,7 @@ public partial class Compare : ICompare, IDisposable
{ {
string seasonDirectory; string seasonDirectory;
DirectoryInfo directoryInfo; DirectoryInfo directoryInfo;
DateTime dateTime = new(ticks); DateTime dateTime = new(compare.Ticks);
string rootDirectory = appSettings.ResultSettings.RootDirectory; string rootDirectory = appSettings.ResultSettings.RootDirectory;
(int season, string seasonName) = IDate.GetSeason(dateTime.DayOfYear); (int season, string seasonName) = IDate.GetSeason(dateTime.DayOfYear);
string eDistanceContentDirectory = IResult.GetResultsDateGroupDirectory(appSettings.ResultSettings, nameof(E_Distance), appSettings.ResultSettings.ResultContent); string eDistanceContentDirectory = IResult.GetResultsDateGroupDirectory(appSettings.ResultSettings, nameof(E_Distance), appSettings.ResultSettings.ResultContent);
@ -153,16 +159,127 @@ public partial class Compare : ICompare, IDisposable
return result; return result;
} }
private static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(AppSettings appSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMappedIdsThenWholePercentagesToLocationContainer(AppSettings appSettings, ICompare compare, ReadOnlyCollections readOnlyCollections)
{ {
ReadOnlyCollection<ExifDirectory> results;
ReadOnlyCollection<ExifDirectory> exifDirectories = IDistance.GetMapped(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.PeopleSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections); ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> results;
if (exifDirectories.Count == 0 && !appSettings.DistanceSettings.SaveSortingWithoutPerson) results = IDistance.GetMappedIdsThenWholePercentagesToLocationContainer(appSettings.ResultSettings,
throw new NotSupportedException($"Switch {nameof(appSettings.DistanceSettings.SaveSortingWithoutPerson)}!"); appSettings.MetadataSettings,
results = IDistance.GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories); appSettings.PeopleSettings,
appSettings.DistanceSettings,
appSettings.CompareSettings,
compare,
readOnlyCollections);
if (results.Count == 0 && !appSettings.DistanceSettings.SaveSortingWithoutPerson) if (results.Count == 0 && !appSettings.DistanceSettings.SaveSortingWithoutPerson)
throw new NotSupportedException($"Switch {nameof(appSettings.DistanceSettings.SaveSortingWithoutPerson)}!"); throw new NotSupportedException($"Switch {nameof(appSettings.DistanceSettings.SaveSortingWithoutPerson)}!");
return results; return results;
} }
private void SaveExtracted(AppSettings appSettings, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer)
{
ReadOnlyCollection<string>? paths;
ReadOnlyDictionary<string, ReadOnlyCollection<string>> rootDirectoryFileNameToPaths = GetRootDirectoryFileNameToPaths(appSettings.ResultSettings, appSettings.CompareSettings);
foreach (KeyValuePair<int, ReadOnlyDictionary<int, LocationContainer>> keyValuePair in mappedIdsThenWholePercentagesToLocationContainer)
{
foreach (KeyValuePair<int, LocationContainer> keyValue in keyValuePair.Value)
{
if (keyValue.Value.ExifDirectory is null || keyValue.Value.FaceFile?.Location is null)
continue;
if (rootDirectoryFileNameToPaths.TryGetValue(keyValue.Value.FilePath.FileNameFirstSegment, out paths))
{
if (appSettings.CompareSettings.SaveExtractedJavaScriptObjectNotation && keyValue.Value.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is not null)
SaveExtractedJavaScriptObjectNotation(keyValue.Key, keyValue.Value, paths);
if (appSettings.CompareSettings.SaveExtractedFaces)
SaveExtractedFace(keyValuePair.Key, keyValue.Key, keyValue.Value.ExifDirectory, keyValue.Value.FaceFile.Location, keyValue.Value.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, paths);
}
}
}
}
private static void SaveExtracted(AppSettings appSettings, ReadOnlyCollection<LocationContainer> preFiltered)
{
ReadOnlyCollection<string>? paths;
ReadOnlyDictionary<string, ReadOnlyCollection<string>> rootDirectoryFileNameToPaths = GetRootDirectoryFileNameToPaths(appSettings.ResultSettings, appSettings.CompareSettings);
foreach (LocationContainer locationContainer in preFiltered)
{
if (locationContainer?.FilePath?.Id is null || locationContainer?.WholePercentages is null || locationContainer?.ExifDirectory is null || locationContainer?.FaceFile?.Location is null)
continue;
if (rootDirectoryFileNameToPaths.TryGetValue(locationContainer.FilePath.FileNameFirstSegment, out paths))
{
if (appSettings.CompareSettings.SaveExtractedJavaScriptObjectNotation && locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName is not null)
SaveExtractedJavaScriptObjectNotation(locationContainer.WholePercentages.Value, locationContainer, paths);
if (appSettings.CompareSettings.SaveExtractedFaces)
SaveExtractedFace(locationContainer.FilePath.Id.Value, locationContainer.WholePercentages.Value, locationContainer.ExifDirectory, locationContainer.FaceFile.Location, locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, paths);
}
}
}
private static ReadOnlyDictionary<string, ReadOnlyCollection<string>> GetRootDirectoryFileNameToPaths(ResultSettings resultSettings, CompareSettings compareSettings)
{
Dictionary<string, ReadOnlyCollection<string>> results = [];
string key;
string extension;
List<string>? collection;
Dictionary<string, List<string>> keyValuePairs = [];
string[] files = !compareSettings.SaveExtractedFaces && !compareSettings.SaveExtractedJavaScriptObjectNotation ? [] : Directory.GetFiles(resultSettings.RootDirectory, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
extension = Path.GetExtension(file);
if (resultSettings.IgnoreExtensions.Contains(extension))
continue;
key = Path.GetFileNameWithoutExtension(file);
if (!keyValuePairs.TryGetValue(key, out collection))
{
keyValuePairs.Add(key, []);
if (!keyValuePairs.TryGetValue(key, out collection))
throw new Exception();
}
collection.Add(file);
}
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
return results.AsReadOnly();
}
private static void SaveExtractedJavaScriptObjectNotation(int wholePercentages, LocationContainer locationContainer, ReadOnlyCollection<string> paths)
{
string file;
string json;
foreach (string path in paths)
{
json = locationContainer.GetWithoutEncoding();
file = $"{path}-{wholePercentages}.json";
_ = IPath.WriteAllText(file, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
}
private static void SaveExtractedFace(int id, int wholePercentages, ExifDirectory _, Location location, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName, ReadOnlyCollection<string> paths)
{
int width;
int height;
string person;
foreach (string path in paths)
{
width = location.Right - location.Left;
height = location.Bottom - location.Top;
person = personKeyFormattedAndKeyTicksAndDisplayDirectoryName is null ? string.Empty : $"-{personKeyFormattedAndKeyTicksAndDisplayDirectoryName.DisplayDirectoryName}";
ExtractFace(file: path,
width: width,
height: height,
left: location.Left,
top: location.Top,
suffix: $"-{id}-{wholePercentages}{person}-face.jpg");
}
}
private static void ExtractFace(string file, float width, float height, double left, double top, string suffix)
{
RectangleF rectangle = new((float)left, (float)top, width, height);
using Bitmap source = new(file);
using Bitmap bitmap = new((int)width, (int)height);
using (Graphics graphics = Graphics.FromImage(bitmap))
graphics.DrawImage(source, new RectangleF(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
bitmap.Save($"{file}{suffix}");
}
} }

View File

@ -1,7 +1,7 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
namespace View_by_Distance.Compare.Models; namespace View_by_Distance.Compare.Models;

View File

@ -1,4 +1,5 @@
using Phares.Shared.Models.Properties;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -9,7 +10,9 @@ public record CompareSettings(string Company,
string FacesHiddenFileNameExtension, string FacesHiddenFileNameExtension,
string FacesPartsFileNameExtension, string FacesPartsFileNameExtension,
int MaxDegreeOfParallelism, int MaxDegreeOfParallelism,
string[] OutputResolutions) : Shared.Models.Properties.ICompareSettings string[] OutputResolutions,
bool SaveExtractedFaces,
bool SaveExtractedJavaScriptObjectNotation) : ICompareSettings
{ {
public override string ToString() public override string ToString()

View File

@ -23,7 +23,7 @@ public class Program
{ {
if (args is null) if (args is null)
throw new Exception("args is null!"); throw new Exception("args is null!");
Shared.Models.Console console = new(); Phares.Shared.Models.Console console = new();
_ = new Compare(args, logger, appSettings, silentIndex > -1, console); _ = new Compare(args, logger, appSettings, silentIndex > -1, console);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -10,7 +10,7 @@
<HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024> <HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.Distance</PackageId> <PackageId>Phares.Distance</PackageId>
<Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version> <Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version>
<Company>Phares</Company> <Company>Phares</Company>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>

View File

@ -1,3 +1,3 @@
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class C_Resize() { } public class C_Resize() { }

View File

@ -1,3 +1,3 @@
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class D2_FaceParts() { } public class D2_FaceParts() { }

View File

@ -1,7 +1,7 @@
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Methods; using Phares.Shared.Models.Methods;
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class DistanceLimits : IDistanceLimits public class DistanceLimits : IDistanceLimits
{ {

View File

@ -1,3 +1,3 @@
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class E_Distance() { } public class E_Distance() { }

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Methods; namespace Phares.Shared.Models.Methods;
public interface IDistanceLimits public interface IDistanceLimits
{ {

View File

@ -1,34 +1,129 @@
using Phares.Shared.Models;
using Phares.Shared.Models.Properties;
using Phares.Shared.Models.Stateless;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
internal static class FaceEncodingLogic internal static class FaceEncodingLogic
{ {
internal static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) internal static void MoveUnableToMatch(FilePath filePath)
{ {
List<ExifDirectory> results = []; string checkFile = $"{filePath.FullName}.unk";
string? json; if (File.Exists(filePath.FullName) && !File.Exists(checkFile))
FaceEncoding? faceEncoding; File.Move(filePath.FullName, checkFile);
ExifDirectory exifDirectory; }
FaceRecognitionDotNet.Models.FaceEncoding? encoding;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMappedIdsThenWholePercentagesToLocationContainer(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections)
{
ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> results;
List<LocationContainer?> locationContainers = [];
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
ReadOnlyCollection<ExifDirectory> exifDirectories = MappedLogicA.GetMapped(resultSettings,
metadataSettings,
peopleSettings,
distanceSettings,
compareSettings,
compare,
readOnlyCollections);
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
string message = $") Building Mapped with Encoding Face Files Collection - {totalSeconds} total second(s)"; string message = $") Building Mapped with Encoding Face Files Collection - {totalSeconds} total second(s)";
compare.ConstructProgressBar(exifDirectories.Count, message); compare.ConstructProgressBar(exifDirectories.Count, message);
foreach (ExifDirectory e in exifDirectories) _ = Parallel.For(0, exifDirectories.Count, parallelOptions, (i, state) =>
LocationContainersParallelFor(distanceSettings, compareSettings, compare, exifDirectories, i, locationContainers));
results = GetMappedIdsThenWholePercentagesToLocationContainer(locationContainers);
return results;
}
private static void LocationContainersParallelFor(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> exifDirectories, int i, List<LocationContainer?> results)
{
compare.Tick();
ExifDirectory exifDirectory = exifDirectories[i];
LocationContainer? locationContainer = GetLocationContainer(distanceSettings, compareSettings, exifDirectory);
results.Add(locationContainer);
}
internal static LocationContainer? GetLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ExifDirectory exifDirectory)
{
LocationContainer? result;
DateOnly dateOnly;
FaceFile? faceFile;
int? wholePercentages;
FaceEncoding? faceEncoding;
FaceRecognitionDotNet.Models.FaceEncoding? encoding;
wholePercentages = IMapping.GetWholePercentages(compareSettings, exifDirectory.FilePath);
if (wholePercentages is null)
{ {
compare.Tick(); if (distanceSettings.DistanceMoveUnableToMatch)
json = Metadata.Models.Stateless.IMetadata.GetFaceEncoding(e); MoveUnableToMatch(exifDirectory.FilePath);
faceEncoding = json is null ? null : JsonSerializer.Deserialize(json, FaceEncodingGenerationContext.Default.FaceEncoding); result = null;
if (faceEncoding is null)
continue;
encoding = FaceRecognitionDotNet.Models.FaceRecognition.LoadFaceEncoding(faceEncoding.RawEncoding);
exifDirectory = ExifDirectory.Get(encoding, e);
results.Add(exifDirectory);
} }
else
{
faceFile = GetFaceFile(distanceSettings, exifDirectory);
if (faceFile is null)
result = null;
else
{
dateOnly = DateOnly.FromDateTime(new DateTime(exifDirectory.FilePath.CreationTicks));
faceEncoding = Phares.Metadata.Models.Stateless.IMetadata.GetFaceEncoding(exifDirectory);
if (faceEncoding is null)
result = null;
else
{
encoding = FaceRecognitionDotNet.Models.FaceRecognition.LoadFaceEncoding(faceEncoding.RawEncoding);
result = new(CreationDateOnly: dateOnly,
ExifDirectory: exifDirectory,
Encoding: encoding,
FaceFile: faceFile,
FilePath: exifDirectory.FilePath,
LengthPermyriad: null,
LengthSource: null,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: exifDirectory.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
WholePercentages: wholePercentages);
}
}
}
return result;
}
private static FaceFile? GetFaceFile(DistanceSettings distanceSettings, ExifDirectory exifDirectory)
{
FaceFile? result = Phares.Metadata.Models.Stateless.IMetadata.GetFaceFile(exifDirectory);
if (result is null || result.Location is null)
{
if (distanceSettings.DistanceMoveUnableToMatch)
MoveUnableToMatch(exifDirectory.FilePath);
result = null;
}
return result;
}
private static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMappedIdsThenWholePercentagesToLocationContainer(List<LocationContainer?> locationContainers)
{
Dictionary<int, ReadOnlyDictionary<int, LocationContainer>> results = [];
int id;
int wholePercentages;
Dictionary<int, LocationContainer>? keyValue;
Dictionary<int, Dictionary<int, LocationContainer>> keyValuePairs = [];
foreach (LocationContainer? locationContainer in locationContainers)
{
if (locationContainer?.FilePath.Id is null || locationContainer.WholePercentages is null)
continue;
id = locationContainer.FilePath.Id.Value;
wholePercentages = locationContainer.WholePercentages.Value;
if (!keyValuePairs.TryGetValue(id, out keyValue))
{
keyValuePairs.Add(id, []);
if (!keyValuePairs.TryGetValue(id, out keyValue))
throw new Exception();
}
keyValue.Add(wholePercentages, locationContainer);
}
foreach (KeyValuePair<int, Dictionary<int, LocationContainer>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
return results.AsReadOnly(); return results.AsReadOnly();
} }

View File

@ -1,8 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text.Json; using Phares.Shared.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Stateless;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -32,20 +31,19 @@ internal static class FilterLogicA
return result; return result;
} }
internal static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) internal static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<ExifDirectory> exifDirectories)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
string? json;
string? model; string? model;
bool? canReMap; bool? canReMap;
bool? isFocusPerson; bool? isFocusPerson;
bool? inSkipCollection; bool? inSkipCollection;
FaceEncoding? faceEncoding; FaceEncoding? faceEncoding;
ReadOnlyDictionary<int, FilePath>? keyValues;
FaceRecognitionDotNet.Models.FaceEncoding? encoding; FaceRecognitionDotNet.Models.FaceEncoding? encoding;
ReadOnlyDictionary<int, LocationContainer>? keyValues;
List<FilePathAndWholePercentages>? wholePercentagesCollection; List<FilePathAndWholePercentages>? wholePercentagesCollection;
ReadOnlyCollection<LocationContainer> locationContainers = FilterLogicB.GetLocationContainers(distanceSettings, compareSettings, compare, ticks, exifDirectories, nameof(FilterLogicA)); ReadOnlyCollection<LocationContainer> locationContainers = FilterLogicB.GetLocationContainers(distanceSettings, compareSettings, compare, exifDirectories, nameof(FilterLogicA));
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
string message = $") PreFiltering LocationContainers Face Files Collection - {totalSeconds} total second(s)"; string message = $") PreFiltering LocationContainers Face Files Collection - {totalSeconds} total second(s)";
compare.ConstructProgressBar(locationContainers.Count, message); compare.ConstructProgressBar(locationContainers.Count, message);
foreach (LocationContainer locationContainer in locationContainers) foreach (LocationContainer locationContainer in locationContainers)
@ -53,7 +51,7 @@ internal static class FilterLogicA
compare.Tick(); compare.Tick();
if (locationContainer.FilePath.Id is null || locationContainer.WholePercentages is null) if (locationContainer.FilePath.Id is null || locationContainer.WholePercentages is null)
continue; continue;
if (keyValuePairs.TryGetValue(locationContainer.FilePath.Id.Value, out keyValues)) if (mappedIdsThenWholePercentagesToLocationContainer.TryGetValue(locationContainer.FilePath.Id.Value, out keyValues))
{ {
if (keyValues.ContainsKey(locationContainer.WholePercentages.Value)) if (keyValues.ContainsKey(locationContainer.WholePercentages.Value))
continue; continue;
@ -71,7 +69,7 @@ internal static class FilterLogicA
continue; continue;
if (!string.IsNullOrEmpty(distanceSettings.FocusModel)) if (!string.IsNullOrEmpty(distanceSettings.FocusModel))
{ {
model = Metadata.Models.Stateless.IMetadata.GetModel(locationContainer.ExifDirectory); model = IMetaBase.GetModel(locationContainer.ExifDirectory);
if (string.IsNullOrEmpty(model) || !model.Contains(distanceSettings.FocusModel)) if (string.IsNullOrEmpty(model) || !model.Contains(distanceSettings.FocusModel))
continue; continue;
} }
@ -80,12 +78,11 @@ internal static class FilterLogicA
if (!locationContainer.FilePath.DirectoryFullPath.Contains(distanceSettings.FocusDirectory)) if (!locationContainer.FilePath.DirectoryFullPath.Contains(distanceSettings.FocusDirectory))
continue; continue;
} }
json = Metadata.Models.Stateless.IMetadata.GetFaceEncoding(locationContainer.ExifDirectory); faceEncoding = Phares.Metadata.Models.Stateless.IMetadata.GetFaceEncoding(locationContainer.ExifDirectory);
faceEncoding = json is null ? null : JsonSerializer.Deserialize(json, FaceEncodingGenerationContext.Default.FaceEncoding);
if (faceEncoding is null) if (faceEncoding is null)
continue; continue;
encoding = FaceRecognitionDotNet.Models.FaceRecognition.LoadFaceEncoding(faceEncoding.RawEncoding); encoding = FaceRecognitionDotNet.Models.FaceRecognition.LoadFaceEncoding(faceEncoding.RawEncoding);
results.Add(LocationContainer.Get(locationContainer, encoding, keepExifDirectory: false)); results.Add(LocationContainer.Get(locationContainer, encoding));
} }
return results.AsReadOnly(); return results.AsReadOnly();
} }

View File

@ -1,80 +1,37 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Drawing; using Phares.Shared.Models;
using System.Text.Json; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models; using Phares.Shared.Models.Stateless;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
internal static class FilterLogicB internal static class FilterLogicB
{ {
private static void MoveUnableToMatch(FilePath filePath) internal static ReadOnlyCollection<LocationContainer> GetLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> exifDirectories, string sourceClass)
{
string checkFile = $"{filePath.FullName}.unk";
if (File.Exists(filePath.FullName) && !File.Exists(checkFile))
File.Move(filePath.FullName, checkFile);
}
private static void LocationContainersParallelFor(DistanceSettings distanceSettings, ICompareSettings compareSettings, List<LocationContainer> locationContainers, ExifDirectory exifDirectory)
{
string? json;
if (exifDirectory.FilePath.Id is null)
return;
DateOnly dateOnly = DateOnly.FromDateTime(new DateTime(exifDirectory.FilePath.CreationTicks));
int? wholePercentages = IMapping.GetWholePercentages(compareSettings, exifDirectory.FilePath);
if (wholePercentages is null)
{
if (distanceSettings.DistanceMoveUnableToMatch)
MoveUnableToMatch(exifDirectory.FilePath);
return;
}
json = Metadata.Models.Stateless.IMetadata.GetOutputResolution(exifDirectory);
if (json is null || !json.Contains(nameof(DateTime)))
{
if (distanceSettings.DistanceMoveUnableToMatch)
MoveUnableToMatch(exifDirectory.FilePath);
return;
}
FaceFile? faceFile = JsonSerializer.Deserialize(json, FaceFileGenerationContext.Default.FaceFile);
if (faceFile is null || faceFile.Location is null)
{
if (distanceSettings.DistanceMoveUnableToMatch)
MoveUnableToMatch(exifDirectory.FilePath);
return;
}
RectangleF? rectangle = Shared.Models.Stateless.ILocation.GetPercentagesRectangle(distanceSettings, wholePercentages.Value);
if (rectangle is null)
return;
LocationContainer locationContainer = new(dateOnly,
exifDirectory,
exifDirectory.Encoding,
faceFile,
exifDirectory.FilePath,
null,
null,
exifDirectory.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
rectangle,
wholePercentages);
lock (locationContainers)
locationContainers.Add(locationContainer);
}
internal static ReadOnlyCollection<LocationContainer> GetLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories, string sourceClass)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism; int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
string message = $") Building LocationContainers Face Files Collection {sourceClass} - {totalSeconds} total second(s)"; string message = $") Building LocationContainers Face Files Collection {sourceClass} - {totalSeconds} total second(s)";
compare.ConstructProgressBar(exifDirectories.Count, message); compare.ConstructProgressBar(exifDirectories.Count, message);
_ = Parallel.For(0, exifDirectories.Count, parallelOptions, (i, state) => _ = Parallel.For(0, exifDirectories.Count, parallelOptions, (i, state) =>
{ LocationContainersParallelFor(distanceSettings, compareSettings, compare, exifDirectories, i, results));
compare.Tick();
LocationContainersParallelFor(distanceSettings, compareSettings, results, exifDirectories[i]);
});
return results.AsReadOnly(); return results.AsReadOnly();
} }
private static void LocationContainersParallelFor(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> exifDirectories, int i, List<LocationContainer> results)
{
compare.Tick();
ExifDirectory exifDirectory = exifDirectories[i];
if (exifDirectory.FilePath.Id is null)
return;
LocationContainer? locationContainer = FaceEncodingLogic.GetLocationContainer(distanceSettings, compareSettings, exifDirectory);
if (locationContainer is null)
return;
lock (results)
results.Add(locationContainer);
}
} }

View File

@ -1,7 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -24,23 +24,25 @@ internal static class FilterLogicC
return results.AsReadOnly(); return results.AsReadOnly();
} }
private static ReadOnlyCollection<LocationContainer> GetCombined(DistanceSettings distanceSettings, Shared.Models.Properties.ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories, ReadOnlyCollection<LocationContainer> postFiltered) private static ReadOnlyCollection<LocationContainer> GetCombined(ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<LocationContainer> postFiltered)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
foreach (LocationContainer locationContainer in postFiltered) foreach (LocationContainer locationContainer in postFiltered)
results.Add(locationContainer); results.Add(locationContainer);
ReadOnlyCollection<LocationContainer> locationContainers = FilterLogicB.GetLocationContainers(distanceSettings, compareSettings, compare, ticks, exifDirectories, nameof(FilterLogicC)); foreach (KeyValuePair<int, ReadOnlyDictionary<int, LocationContainer>> keyValuePair in mappedIdsThenWholePercentagesToLocationContainer)
foreach (LocationContainer locationContainer in locationContainers) {
results.Add(locationContainer); foreach (KeyValuePair<int, LocationContainer> keyValue in keyValuePair.Value)
results.Add(keyValue.Value);
}
return results.AsReadOnly(); return results.AsReadOnly();
} }
internal static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, Shared.Models.Properties.ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) internal static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompare compare, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
ReadOnlyCollection<LocationContainer> collection; ReadOnlyCollection<LocationContainer> collection;
ReadOnlyCollection<LocationContainer> locationContainers = GetCombined(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, postFiltered); ReadOnlyCollection<LocationContainer> locationContainers = GetCombined(mappedIdsThenWholePercentagesToLocationContainer, postFiltered);
string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds)} total second(s)";
compare.ConstructProgressBar(postFiltered.Count, message); compare.ConstructProgressBar(postFiltered.Count, message);
foreach (LocationContainer locationContainer in postFiltered) foreach (LocationContainer locationContainer in postFiltered)
{ {

View File

@ -1,9 +1,9 @@
using Humanizer; using Humanizer;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
using WindowsShortcutFactory; using WindowsShortcutFactory;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -55,7 +55,7 @@ internal static class FilterLogicD
return result; return result;
} }
internal static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) internal static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers)
{ {
string fileName; string fileName;
string checkFile; string checkFile;
@ -70,7 +70,7 @@ internal static class FilterLogicD
if (!Directory.Exists(directory)) if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory); _ = Directory.CreateDirectory(directory);
} }
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
string message; string message;
if (updated is null) if (updated is null)
message = $") {saveContainers.Count:000} save(s) - {totalSeconds} total second(s)"; message = $") {saveContainers.Count:000} save(s) - {totalSeconds} total second(s)";
@ -166,7 +166,7 @@ internal static class FilterLogicD
} }
} }
internal static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) internal static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne)
{ {
List<SaveContainer> results = []; List<SaveContainer> results = [];
RecordB recordB; RecordB recordB;
@ -205,14 +205,14 @@ internal static class FilterLogicD
string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, resultSettings.ResultContent); string cContentDirectory = Path.Combine(cResultsFullGroupDirectory, resultSettings.ResultContent);
if (!Directory.Exists(cContentDirectory)) if (!Directory.Exists(cContentDirectory))
_ = Directory.CreateDirectory(cContentDirectory); _ = Directory.CreateDirectory(cContentDirectory);
string eDistanceContentTicksDirectory = Path.Combine(eResultsFullGroupDirectory, ticks.ToString()); string eDistanceContentTicksDirectory = Path.Combine(eResultsFullGroupDirectory, compare.Ticks.ToString());
if (!Directory.Exists(eDistanceContentTicksDirectory)) if (!Directory.Exists(eDistanceContentTicksDirectory))
_ = Directory.CreateDirectory(eDistanceContentTicksDirectory); _ = Directory.CreateDirectory(eDistanceContentTicksDirectory);
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, resultSettings.ResultContent); string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, resultSettings.ResultContent);
if (!Directory.Exists(d2FacePartsContentDirectory)) if (!Directory.Exists(d2FacePartsContentDirectory))
_ = Directory.CreateDirectory(d2FacePartsContentDirectory); _ = Directory.CreateDirectory(d2FacePartsContentDirectory);
string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title); string forceSingleImageHumanized = nameof(IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
string message = $") Building Save Container Collection - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; string message = $") Building Save Container Collection - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds)} total second(s)";
compare.ConstructProgressBar(onlyOne.Count, message); compare.ConstructProgressBar(onlyOne.Count, message);
foreach (KeyValuePair<string, LocationContainer> keyValuePair in onlyOne) foreach (KeyValuePair<string, LocationContainer> keyValuePair in onlyOne)
{ {

View File

@ -1,15 +1,15 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
public interface IDistance public interface IDistance
{ {
static string Get(bool saveIndividually, string forceSingleImageHumanized, int by, bool isDefaultName) => public static string Get(bool saveIndividually, string forceSingleImageHumanized, int by, bool isDefaultName) =>
$"{by switch $"{by switch
{ {
IMapLogic.Mapping => nameof(IMapLogic.Mapping), IMapLogic.Mapping => nameof(IMapLogic.Mapping),
@ -23,55 +23,43 @@ public interface IDistance
public static ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) => public static ReadOnlyDictionary<string, LocationContainer> GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
FilterLogicC.GetOnlyOne(distanceSettings, matrix); FilterLogicC.GetOnlyOne(distanceSettings, matrix);
public static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
FaceEncodingLogic.GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
public static ReadOnlyCollection<LocationContainer> GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) => public static ReadOnlyCollection<LocationContainer> GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
FilterLogicC.GetPostFilterLocationContainer(preFiltered, distanceLimits); FilterLogicC.GetPostFilterLocationContainer(preFiltered, distanceLimits);
public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) => public static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
MappedLogicA.Extract(compareSettings, exifDirectories); FilterLogicD.SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers);
public static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) => public static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
FilterLogicD.SaveContainers(distanceSettings, compareSettings, compare, ticks, updated, saveContainers); FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne);
public static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) => public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompare compare, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne); FilterLogicC.GetMatrixLocationContainers(distanceSettings, compare, mappedIdsThenWholePercentagesToLocationContainer, distanceLimits, postFiltered);
public static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) => public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMappedIdsThenWholePercentagesToLocationContainer(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) =>
MappedLogicA.GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections); FaceEncodingLogic.GetMappedIdsThenWholePercentagesToLocationContainer(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections);
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) => public static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
FilterLogicC.GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered); FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, mappedIdsThenWholePercentagesToLocationContainer, exifDirectories);
public static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
internal static ReadOnlyDictionary<string, LocationContainer> TestStatic_GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) => internal static ReadOnlyDictionary<string, LocationContainer> TestStatic_GetOnlyOne(DistanceSettings distanceSettings, ReadOnlyCollection<LocationContainer> matrix) =>
GetOnlyOne(distanceSettings, matrix); GetOnlyOne(distanceSettings, matrix);
internal static ReadOnlyCollection<ExifDirectory> TestStatic_GetMappedExifDirectoryWithEncoding(ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) => internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPostFilterLocationContainer(ReadOnlyCollection<LocationContainer> preFiltered, DistanceLimits distanceLimits) =>
GetPostFilterLocationContainer(preFiltered, distanceLimits); GetPostFilterLocationContainer(preFiltered, distanceLimits);
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> TestStatic_Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) => internal static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
Extract(compareSettings, exifDirectories); SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers);
internal static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) => internal static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
SaveContainers(distanceSettings, compareSettings, compare, ticks, updated, saveContainers); GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne);
internal static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) => internal static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompare compare, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, ticks, outputResolution, onlyOne); GetMatrixLocationContainers(distanceSettings, compare, mappedIdsThenWholePercentagesToLocationContainer, distanceLimits, postFiltered);
internal static ReadOnlyCollection<ExifDirectory> TestStatic_GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections) => internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> TestStatic_GetMappedIdsThenWholePercentagesToLocationContainer(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) =>
GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, readOnlyCollections); GetMappedIdsThenWholePercentagesToLocationContainer(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections);
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) => internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
GetMatrixLocationContainers(distanceSettings, compareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered); GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, mappedIdsThenWholePercentagesToLocationContainer, exifDirectories);
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
} }

View File

@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Metadata.Models.Stateless; using Phares.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -14,42 +14,16 @@ internal static class MappedLogicA
string? PersonDisplayDirectoryName, string? PersonDisplayDirectoryName,
FilePath FilePath); FilePath FilePath);
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> Extract(ICompareSettings compareSettings, ReadOnlyCollection<ExifDirectory> exifDirectories) internal static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections)
{
Dictionary<int, ReadOnlyDictionary<int, FilePath>> results = [];
int? wholePercentages;
Dictionary<int, FilePath>? keyValues;
Dictionary<int, Dictionary<int, FilePath>> keyValuePairs = [];
foreach (ExifDirectory exifDirectory in exifDirectories)
{
if (exifDirectory.FilePath.Id is null)
continue;
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
{
keyValuePairs.Add(exifDirectory.FilePath.Id.Value, []);
if (!keyValuePairs.TryGetValue(exifDirectory.FilePath.Id.Value, out keyValues))
throw new Exception();
}
wholePercentages = IMapping.GetWholePercentages(compareSettings, exifDirectory.FilePath);
if (wholePercentages is null)
continue;
keyValues.Add(wholePercentages.Value, exifDirectory.FilePath);
}
foreach (KeyValuePair<int, Dictionary<int, FilePath>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
return results.AsReadOnly();
}
internal static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections)
{ {
List<ExifDirectory> results = []; List<ExifDirectory> results = [];
string eDistanceContentDirectory = Path.GetFullPath(IResult.GetResultsDateGroupDirectory(resultSettings, nameof(E_Distance), resultSettings.ResultContent)); string eDistanceContentDirectory = Path.GetFullPath(IResult.GetResultsDateGroupDirectory(resultSettings, nameof(E_Distance), resultSettings.ResultContent));
ReadOnlyCollection<MappedLogicB.Record> records = MappedLogicB.DeleteEmptyDirectoriesAndGetCollection(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, ticks, eDistanceContentDirectory, readOnlyCollections); ReadOnlyCollection<MappedLogicB.Record> records = MappedLogicB.DeleteEmptyDirectoriesAndGetCollection(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, eDistanceContentDirectory, readOnlyCollections);
ReadOnlyCollection<MappedFile> mappedFiles = GetMappedFiles(resultSettings, metadataSettings, peopleSettings, compareSettings, readOnlyCollections, records); ReadOnlyCollection<MappedFile> mappedFiles = GetMappedFiles(resultSettings, metadataSettings, peopleSettings, compareSettings, readOnlyCollections, records);
if (mappedFiles.Count > 0) if (mappedFiles.Count > 0)
{ {
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism; int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)"; string message = $") Building Mapped Face Files Collection - {totalSeconds} total second(s)";
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
ReadOnlyDictionary<int, List<FilePathAndWholePercentages>> skipNotSkipCollection = readOnlyCollections.SkipNotSkipCollection; ReadOnlyDictionary<int, List<FilePathAndWholePercentages>> skipNotSkipCollection = readOnlyCollections.SkipNotSkipCollection;

View File

@ -2,9 +2,9 @@ using Humanizer;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -24,7 +24,7 @@ internal static class MappedLogicB
bool? IsLocationContainerDebugDirectory, bool? IsLocationContainerDebugDirectory,
float? TotalDays); float? TotalDays);
internal static ReadOnlyCollection<Record> DeleteEmptyDirectoriesAndGetCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string eDistanceContentDirectory, ReadOnlyCollections readOnlyCollections) internal static ReadOnlyCollection<Record> DeleteEmptyDirectoriesAndGetCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string eDistanceContentDirectory, ReadOnlyCollections readOnlyCollections)
{ {
List<Record> results = []; List<Record> results = [];
bool check; bool check;
@ -59,7 +59,7 @@ internal static class MappedLogicB
distinct.Clear(); distinct.Clear();
directoryNumber = 0; directoryNumber = 0;
ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(distanceSettings, eDistanceContentDirectory); ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(distanceSettings, eDistanceContentDirectory);
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)";
compare.ConstructProgressBar(ticksDirectories.Count, message); compare.ConstructProgressBar(ticksDirectories.Count, message);
foreach (TicksDirectory ticksDirectory in ticksDirectories) foreach (TicksDirectory ticksDirectory in ticksDirectories)

View File

@ -10,7 +10,7 @@
<HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024> <HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.Face</PackageId> <PackageId>Phares.Face</PackageId>
<Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version> <Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version>
<Company>Phares</Company> <Company>Phares</Company>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>

View File

@ -1,3 +1,3 @@
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class D_Face() { } public class D_Face() { }

View File

@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Metadata.Models.Stateless; using Phares.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Face.Models.Stateless; namespace View_by_Distance.Face.Models.Stateless;
@ -21,13 +21,13 @@ internal static class Face
results.Add(exifDirectory); results.Add(exifDirectory);
} }
internal static ReadOnlyCollection<ExifDirectory> GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution) internal static ReadOnlyCollection<ExifDirectory> GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution)
{ {
List<ExifDirectory> results = []; List<ExifDirectory> results = [];
FileInfo fileInfo; FileInfo fileInfo;
int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism; int maxDegreeOfParallelism = compareSettings.MaxDegreeOfParallelism;
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
long? skipOlderThan = distanceSettings.SkipOlderThanDays < 1 ? null : new DateTime(ticks).AddDays(-distanceSettings.SkipOlderThanDays).Ticks; long? skipOlderThan = distanceSettings.SkipOlderThanDays < 1 ? null : new DateTime(compare.Ticks).AddDays(-distanceSettings.SkipOlderThanDays).Ticks;
string resultsFullGroupDirectory = Path.GetFullPath(IResult.GetResultsFullGroupDirectory(resultSettings, string resultsFullGroupDirectory = Path.GetFullPath(IResult.GetResultsFullGroupDirectory(resultSettings,
nameof(D_Face), nameof(D_Face),
outputResolution, outputResolution,

View File

@ -1,16 +1,16 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Face.Models.Stateless; namespace View_by_Distance.Face.Models.Stateless;
public interface IFace public interface IFace
{ {
ReadOnlyCollection<ExifDirectory> TestStatic_GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution) => ReadOnlyCollection<ExifDirectory> TestStatic_GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution) =>
GetExifDirectories(resultSettings, metadataSettings, distanceSettings, compareSettings, compare, ticks, outputResolution); GetExifDirectories(resultSettings, metadataSettings, distanceSettings, compareSettings, compare, outputResolution);
static ReadOnlyCollection<ExifDirectory> GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, long ticks, string outputResolution) => static ReadOnlyCollection<ExifDirectory> GetExifDirectories(ResultSettings resultSettings, MetadataSettings metadataSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution) =>
Face.GetExifDirectories(resultSettings, metadataSettings, distanceSettings, compareSettings, compare, ticks, outputResolution); Face.GetExifDirectories(resultSettings, metadataSettings, distanceSettings, compareSettings, compare, outputResolution);
} }

View File

@ -10,7 +10,7 @@
<HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024> <HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.FaceRecognitionDotNet</PackageId> <PackageId>Phares.FaceRecognitionDotNet</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version> <Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>

View File

@ -1,7 +1,7 @@
using DlibDotNet; using DlibDotNet;
using DlibDotNet.Dnn; using DlibDotNet.Dnn;
using View_by_Distance.FaceRecognitionDotNet.Models; using View_by_Distance.FaceRecognitionDotNet.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Dlib.Python; namespace View_by_Distance.FaceRecognitionDotNet.Dlib.Python;

View File

@ -1,6 +1,6 @@
using DlibDotNet; using DlibDotNet;
using View_by_Distance.FaceRecognitionDotNet.Models; using View_by_Distance.FaceRecognitionDotNet.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Dlib.Python; namespace View_by_Distance.FaceRecognitionDotNet.Dlib.Python;

View File

@ -1,6 +1,6 @@
using DlibDotNet; using DlibDotNet;
using View_by_Distance.FaceRecognitionDotNet.Models; using View_by_Distance.FaceRecognitionDotNet.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
namespace View_by_Distance.FaceRecognitionDotNet.Extensions; namespace View_by_Distance.FaceRecognitionDotNet.Extensions;

View File

@ -1,7 +1,7 @@
using DlibDotNet; using DlibDotNet;
using View_by_Distance.FaceRecognitionDotNet.Models; using View_by_Distance.FaceRecognitionDotNet.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Extensions; namespace View_by_Distance.FaceRecognitionDotNet.Extensions;

View File

@ -6,8 +6,8 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using View_by_Distance.FaceRecognitionDotNet.Dlib.Python; using View_by_Distance.FaceRecognitionDotNet.Dlib.Python;
using View_by_Distance.FaceRecognitionDotNet.Extensions; using View_by_Distance.FaceRecognitionDotNet.Extensions;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Models; namespace View_by_Distance.FaceRecognitionDotNet.Models;

View File

@ -1,5 +1,5 @@
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Models; namespace View_by_Distance.FaceRecognitionDotNet.Models;

View File

@ -1,7 +1,7 @@
using DlibDotNet; using DlibDotNet;
using DlibDotNet.Extensions; using DlibDotNet.Extensions;
using System.Drawing; using System.Drawing;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Models; namespace View_by_Distance.FaceRecognitionDotNet.Models;

View File

@ -10,8 +10,8 @@
<HoursSinceNovember142023>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</HoursSinceNovember142023> <HoursSinceNovember142023>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</HoursSinceNovember142023>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.Metadata</PackageId> <PackageId>Phares.Metadata</PackageId>
<Version>8.0.114.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</Version> <Version>8.0.118.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</Version>
<Company>Phares</Company> <Company>Phares</Company>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>

View File

@ -1,10 +1,10 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models.Stateless; using Phares.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class A_Metadata public class A_Metadata
{ {
@ -36,45 +36,8 @@ public class A_Metadata
} }
} }
_ResultSingletonFileGroups = new(results); _ResultSingletonFileGroups = new(results);
} ReadOnlyCollection<string> directories = new([Path.Combine(aResultsFullGroupDirectory, resultSettings.ResultSingleton)]);
IPath.CreateDirectories(directories);
private MinimumYearAndPathCombined GetMinimumYearAndPathCombined(ResultSettings resultSettings, FilePath filePath)
{
MinimumYearAndPathCombined result;
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
DateTime minimumDateTime = new(filePath.CreationTicks < filePath.LastWriteTicks ? filePath.CreationTicks : filePath.LastWriteTicks);
int minimumYear = minimumDateTime.Year < resultSettings.EpicYear ? resultSettings.EpicYear : minimumDateTime.Year;
result = new(minimumYear, Path.Combine(_ResultSingletonFileGroups[minimumYear][cei.Enum][cei.Index], $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}.json"));
return result;
}
private (int, string) GetJsonFile(ResultSettings resultSettings, FilePath filePath, ExifDirectory exifDirectory)
{
string? result;
DateTime? dateTime;
dateTime = IDate.GetDateTimeOriginal(exifDirectory);
dateTime ??= IDate.GetMinimum(exifDirectory);
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
int exifYear = dateTime.Value.Year < resultSettings.EpicYear ? resultSettings.EpicYear : dateTime.Value.Year;
result = Path.Combine(_ResultSingletonFileGroups[exifYear][cei.Enum][cei.Index], $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}.json");
return new(exifYear, result);
}
private static (string, ExifDirectory?) Get(string jsonFile)
{
ExifDirectory? result;
string json = File.ReadAllText(jsonFile);
try
{
result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
if (result is null)
throw new Exception();
}
catch (Exception)
{
result = null;
}
return new(json, result);
} }
public (MinimumYearAndPathCombined, ExifDirectory) GetMetadataCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, FilePath filePath) public (MinimumYearAndPathCombined, ExifDirectory) GetMetadataCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, FilePath filePath)
@ -148,19 +111,45 @@ public class A_Metadata
return new(minimumYearAndPathCombined, result); return new(minimumYearAndPathCombined, result);
} }
private static Stream GetStream(HttpClient httpClient, FilePath filePath) private MinimumYearAndPathCombined GetMinimumYearAndPathCombined(ResultSettings resultSettings, FilePath filePath)
{ {
Stream result; MinimumYearAndPathCombined result;
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(filePath.FullName); CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
httpResponseMessage.Wait(); DateTime minimumDateTime = new(filePath.CreationTicks < filePath.LastWriteTicks ? filePath.CreationTicks : filePath.LastWriteTicks);
Task task = httpResponseMessage.Result.Content.LoadIntoBufferAsync(); int minimumYear = minimumDateTime.Year < resultSettings.EpicYear ? resultSettings.EpicYear : minimumDateTime.Year;
task.Wait(); result = new(minimumYear, Path.Combine(_ResultSingletonFileGroups[minimumYear][cei.Enum][cei.Index], $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}.json"));
Task<Stream> stream = httpResponseMessage.Result.Content.ReadAsStreamAsync();
stream.Wait();
result = stream.Result;
return result; return result;
} }
private (int, string) GetJsonFile(ResultSettings resultSettings, FilePath filePath, ExifDirectory exifDirectory)
{
string? result;
DateTime? dateTime;
dateTime = IDate.GetDateTimeOriginal(exifDirectory);
dateTime ??= IDate.GetMinimum(exifDirectory);
CombinedEnumAndIndex cei = IPath.GetCombinedEnumAndIndex(resultSettings, filePath);
int exifYear = dateTime.Value.Year < resultSettings.EpicYear ? resultSettings.EpicYear : dateTime.Value.Year;
result = Path.Combine(_ResultSingletonFileGroups[exifYear][cei.Enum][cei.Index], $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}.json");
return new(exifYear, result);
}
private static (string, ExifDirectory?) Get(string jsonFile)
{
ExifDirectory? result;
string json = File.ReadAllText(jsonFile);
try
{
result = JsonSerializer.Deserialize(json, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
if (result is null)
throw new Exception();
}
catch (Exception)
{
result = null;
}
return new(json, result);
}
public (MinimumYearAndPathCombined, ExifDirectory) GetMetadataCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, HttpClient? httpClient, FilePath filePath) public (MinimumYearAndPathCombined, ExifDirectory) GetMetadataCollection(ResultSettings resultSettings, MetadataSettings metadataSettings, HttpClient? httpClient, FilePath filePath)
{ {
ExifDirectory result; ExifDirectory result;
@ -178,4 +167,17 @@ public class A_Metadata
return new(minimumYearAndPathCombined, result); return new(minimumYearAndPathCombined, result);
} }
private static Stream GetStream(HttpClient httpClient, FilePath filePath)
{
Stream result;
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(filePath.FullName);
httpResponseMessage.Wait();
Task task = httpResponseMessage.Result.Content.LoadIntoBufferAsync();
task.Wait();
Task<Stream> stream = httpResponseMessage.Result.Content.ReadAsStreamAsync();
stream.Wait();
result = stream.Result;
return result;
}
} }

View File

@ -1,68 +0,0 @@
using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Metadata.Models.Stateless;
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;
}
}
}
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;
}
}
}
return result;
}
internal static ReadOnlyCollection<string> GetKeywords(ExifDirectoryBase[]? exifBaseDirectories)
{
List<string> results = [];
if (exifBaseDirectories is not null)
{
string value;
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
value = exifDirectoryBase?.WinKeywords is null ? string.Empty : exifDirectoryBase.WinKeywords.ToString().Trim();
if (string.IsNullOrEmpty(value))
continue;
results.Add(value);
}
}
return results.AsReadOnly();
}
}

View File

@ -1,6 +1,6 @@
using System.Drawing; using System.Drawing;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
internal static class Dimensions internal static class Dimensions
{ {
@ -8,18 +8,18 @@ internal static class Dimensions
#pragma warning disable IDE0230 #pragma warning disable IDE0230
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new() private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
{ {
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
{ new byte[] { 0x42, 0x4D }, DecodeBitmap }, { new byte[] { 0x42, 0x4D }, DecodeBitmap },
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif }, { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif }, { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng }, { 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 #pragma warning restore IDE0230
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes) private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
{ {
for (int i = 0; i < thatBytes.Length; i += 1) for (int i = 0; i < thisBytes.Count && i < thatBytes.Length; i += 1)
{ {
if (thisBytes[i] == thatBytes[i]) if (thisBytes[i] == thatBytes[i])
continue; continue;
@ -103,30 +103,49 @@ internal static class Dimensions
internal static Size? GetDimensions(BinaryReader binaryReader) internal static Size? GetDimensions(BinaryReader binaryReader)
{ {
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length; Size? result;
byte[] magicBytes = new byte[maxMagicBytesLength]; List<byte> magicBytes = [];
for (int i = 0; i < maxMagicBytesLength; i += 1) int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
if (magicBytesLengths.Length == 0)
result = null;
else
{ {
magicBytes[i] = binaryReader.ReadByte(); result = null;
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders) if (binaryReader.BaseStream.Length == binaryReader.BaseStream.Position)
_ = binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
for (int i = 0; i < magicBytesLengths[0]; i++)
{ {
if (StartsWith(magicBytes, kvPair.Key)) magicBytes.Add(binaryReader.ReadByte());
return kvPair.Value(binaryReader); foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
{
if (StartsWith(magicBytes, kvPair.Key))
{
result = kvPair.Value(binaryReader);
break;
}
}
if (result is not null)
break;
} }
} }
return null; return result;
} }
internal static Size? GetDimensions(string path) internal static Size? GetDimensions(string path)
{ {
using BinaryReader binaryReader = new(File.OpenRead(path)); Size? result;
return GetDimensions(binaryReader); using FileStream fileStream = File.OpenRead(path);
using BinaryReader binaryReader = new(fileStream);
result = GetDimensions(binaryReader);
return result;
} }
internal static Size? GetDimensions(Stream stream) internal static Size? GetDimensions(Stream stream)
{ {
Size? result;
using BinaryReader binaryReader = new(stream); using BinaryReader binaryReader = new(stream);
return GetDimensions(binaryReader); result = GetDimensions(binaryReader);
return result;
} }
} }

View File

@ -1,9 +1,10 @@
using MetadataExtractor; using MetadataExtractor;
using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.Exif.Makernotes; using MetadataExtractor.Formats.Exif.Makernotes;
using System.Globalization; using System.Globalization;
using Phares.Shared.Models;
using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
internal abstract class Exif internal abstract class Exif
{ {
@ -24,10 +25,10 @@ internal abstract class Exif
return result; return result;
} }
private static Shared.Models.AviDirectory[] GetAviDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static AviDirectory[] GetAviDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.AviDirectory> results = []; List<AviDirectory> results = [];
Shared.Models.AviDirectory aviDirectory; AviDirectory aviDirectory;
IEnumerable<MetadataExtractor.Formats.Avi.AviDirectory> aviDirectories = directories.OfType<MetadataExtractor.Formats.Avi.AviDirectory>(); IEnumerable<MetadataExtractor.Formats.Avi.AviDirectory> aviDirectories = directories.OfType<MetadataExtractor.Formats.Avi.AviDirectory>();
foreach (MetadataExtractor.Formats.Avi.AviDirectory a in aviDirectories) foreach (MetadataExtractor.Formats.Avi.AviDirectory a in aviDirectories)
{ {
@ -43,18 +44,18 @@ internal abstract class Exif
dateTimeOriginal = GetDateTime(a.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal)); dateTimeOriginal = GetDateTime(a.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal));
if (dateTimeOriginal is null && duration is null && height is null && width is null) if (dateTimeOriginal is null && duration is null && height is null && width is null)
continue; continue;
aviDirectory = new(dateTimeOriginal, duration, height, width); aviDirectory = new(DateTimeOriginal: dateTimeOriginal, Duration: duration, Height: height, Width: width);
results.Add(aviDirectory); results.Add(aviDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.ExifDirectoryBase[] GetExifBaseDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static ExifDirectoryBase[] GetExifBaseDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.ExifDirectoryBase> results = []; List<ExifDirectoryBase> results = [];
Shared.Models.ExifDirectoryBase exifDirectoryBase; ExifDirectoryBase exifDirectoryBase;
IEnumerable<ExifDirectoryBase> exifBaseDirectories = directories.OfType<ExifDirectoryBase>(); IEnumerable<MetadataExtractor.Formats.Exif.ExifDirectoryBase> exifBaseDirectories = directories.OfType<MetadataExtractor.Formats.Exif.ExifDirectoryBase>();
foreach (ExifDirectoryBase e in exifBaseDirectories) foreach (MetadataExtractor.Formats.Exif.ExifDirectoryBase e in exifBaseDirectories)
{ {
if (e.Tags.Count == 0) if (e.Tags.Count == 0)
continue; continue;
@ -62,61 +63,63 @@ internal abstract class Exif
DateTime checkDateTime; DateTime checkDateTime;
DateTime? dateTimeOriginal; DateTime? dateTimeOriginal;
DateTime? dateTimeDigitized; DateTime? dateTimeDigitized;
string? aperture = e.GetDescription(ExifDirectoryBase.TagAperture); string? aperture = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagAperture);
string? applicationNotes = e.GetDescription(ExifDirectoryBase.TagApplicationNotes); string? applicationNotes = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagApplicationNotes);
string? artist = e.GetDescription(ExifDirectoryBase.TagArtist); string? artist = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagArtist);
string? bitsPerSample = e.GetDescription(ExifDirectoryBase.TagBitsPerSample); string? bitsPerSample = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagBitsPerSample);
string? bodySerialNumber = e.GetDescription(ExifDirectoryBase.TagBodySerialNumber); string? bodySerialNumber = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagBodySerialNumber);
string? cameraOwnerName = e.GetDescription(ExifDirectoryBase.TagCameraOwnerName); string? cameraOwnerName = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagCameraOwnerName);
string? compressedAverageBitsPerPixel = e.GetDescription(ExifDirectoryBase.TagCompressedAverageBitsPerPixel); string? compressedAverageBitsPerPixel = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagCompressedAverageBitsPerPixel);
string? compression = e.GetDescription(ExifDirectoryBase.TagCompression); string? compression = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagCompression);
string? copyright = e.GetDescription(ExifDirectoryBase.TagCopyright); string? copyright = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagCopyright);
string? documentName = e.GetDescription(ExifDirectoryBase.TagDocumentName); string? documentName = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDocumentName);
string? exifVersion = e.GetDescription(ExifDirectoryBase.TagExifVersion); string? exifVersion = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExifVersion);
string? exposureTime = e.GetDescription(ExifDirectoryBase.TagExposureTime); string? exposureTime = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExposureTime);
string? fileSource = e.GetDescription(ExifDirectoryBase.TagFileSource); string? fileSource = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagFileSource);
string? imageDescription = e.GetDescription(ExifDirectoryBase.TagImageDescription); string? imageDescription = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageDescription);
string? imageHeight = e.GetDescription(ExifDirectoryBase.TagImageHeight); string? imageHeight = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageHeight);
string? imageNumber = e.GetDescription(ExifDirectoryBase.TagImageNumber); int? imageHeightValue = imageHeight is null ? null : e.GetInt32(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageHeight);
string? imageUniqueId = e.GetDescription(ExifDirectoryBase.TagImageUniqueId); string? imageNumber = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageNumber);
string? imageWidth = e.GetDescription(ExifDirectoryBase.TagImageWidth); string? imageUniqueId = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageUniqueId);
string? isoSpeed = e.GetDescription(ExifDirectoryBase.TagIsoSpeed); string? imageWidth = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageWidth);
string? lensMake = e.GetDescription(ExifDirectoryBase.TagLensMake); int? imageWidthValue = imageWidth is null ? null : e.GetInt32(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagImageWidth);
string? lensModel = e.GetDescription(ExifDirectoryBase.TagLensModel); string? isoSpeed = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagIsoSpeed);
string? lensSerialNumber = e.GetDescription(ExifDirectoryBase.TagLensSerialNumber); string? lensMake = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagLensMake);
string? make = e.GetDescription(ExifDirectoryBase.TagMake); string? lensModel = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagLensModel);
string? makerNote = e.GetDescription(ExifDirectoryBase.TagMakernote); string? lensSerialNumber = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagLensSerialNumber);
string? model = e.GetDescription(ExifDirectoryBase.TagModel); string? make = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagMake);
string? orientation = e.GetDescription(ExifDirectoryBase.TagOrientation); string? makerNote = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagMakernote);
int? orientationValue = orientation is null ? null : e.GetInt32(ExifDirectoryBase.TagOrientation); string? model = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModel);
string? rating = e.GetDescription(ExifDirectoryBase.TagRating); string? orientation = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation);
string? ratingPercent = e.GetDescription(ExifDirectoryBase.TagRatingPercent); int? orientationValue = orientation is null ? null : e.GetInt32(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagOrientation);
string? securityClassification = e.GetDescription(ExifDirectoryBase.TagSecurityClassification); string? rating = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagRating);
string? shutterSpeed = e.GetDescription(ExifDirectoryBase.TagShutterSpeed); string? ratingPercent = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagRatingPercent);
string? software = e.GetDescription(ExifDirectoryBase.TagSoftware); string? securityClassification = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSecurityClassification);
string? timeZone = e.GetDescription(ExifDirectoryBase.TagTimeZone); string? shutterSpeed = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagShutterSpeed);
string? timeZoneDigitized = e.GetDescription(ExifDirectoryBase.TagTimeZoneDigitized); string? software = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSoftware);
string? timeZoneOriginal = e.GetDescription(ExifDirectoryBase.TagTimeZoneOriginal); string? timeZone = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagTimeZone);
string? userComment = e.GetDescription(ExifDirectoryBase.TagUserComment); string? timeZoneDigitized = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagTimeZoneDigitized);
string? winAuthor = e.GetDescription(ExifDirectoryBase.TagWinAuthor); string? timeZoneOriginal = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagTimeZoneOriginal);
string? winComment = e.GetDescription(ExifDirectoryBase.TagWinComment); string? userComment = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagUserComment);
string? winKeywords = e.GetDescription(ExifDirectoryBase.TagWinKeywords); string? winAuthor = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinAuthor);
string? winSubject = e.GetDescription(ExifDirectoryBase.TagWinSubject); string? winComment = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinComment);
string? winTitle = e.GetDescription(ExifDirectoryBase.TagWinTitle); string? winKeywords = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinKeywords);
string? xResolution = e.GetDescription(ExifDirectoryBase.TagXResolution); string? winSubject = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinSubject);
string? yResolution = e.GetDescription(ExifDirectoryBase.TagYResolution); string? winTitle = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagWinTitle);
if (e.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime)) string? xResolution = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagXResolution);
string? yResolution = e.GetDescription(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagYResolution);
if (e.TryGetDateTime(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime, out checkDateTime))
dateTime = checkDateTime; dateTime = checkDateTime;
else else
dateTime = GetDateTime(e.GetString(ExifDirectoryBase.TagDateTime)); dateTime = GetDateTime(e.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTime));
if (e.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime)) if (e.TryGetDateTime(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime))
dateTimeOriginal = checkDateTime; dateTimeOriginal = checkDateTime;
else else
dateTimeOriginal = GetDateTime(e.GetString(ExifDirectoryBase.TagDateTimeOriginal)); dateTimeOriginal = GetDateTime(e.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeOriginal));
if (e.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime)) if (e.TryGetDateTime(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime))
dateTimeDigitized = checkDateTime; dateTimeDigitized = checkDateTime;
else else
dateTimeDigitized = GetDateTime(e.GetString(ExifDirectoryBase.TagDateTimeDigitized)); dateTimeDigitized = GetDateTime(e.GetString(MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagDateTimeDigitized));
if (userComment is not null && userComment.Length > 255) if (userComment is not null && userComment.Length > 255)
userComment = "..."; userComment = "...";
if (aperture is null if (aperture is null
@ -166,61 +169,63 @@ internal abstract class Exif
&& xResolution is not null && xResolution is not null
&& yResolution is null) && yResolution is null)
continue; continue;
exifDirectoryBase = new(aperture, exifDirectoryBase = new(Aperture: aperture,
applicationNotes, ApplicationNotes: applicationNotes,
artist, Artist: artist,
bitsPerSample, BitsPerSample: bitsPerSample,
bodySerialNumber, BodySerialNumber: bodySerialNumber,
cameraOwnerName, CameraOwnerName: cameraOwnerName,
compressedAverageBitsPerPixel, CompressedAverageBitsPerPixel: compressedAverageBitsPerPixel,
compression, Compression: compression,
copyright, Copyright: copyright,
dateTime, DateTime: dateTime,
dateTimeDigitized, DateTimeDigitized: dateTimeDigitized,
dateTimeOriginal, DateTimeOriginal: dateTimeOriginal,
documentName, DocumentName: documentName,
exifVersion, ExifVersion: exifVersion,
exposureTime, ExposureTime: exposureTime,
fileSource, FileSource: fileSource,
imageDescription, ImageDescription: imageDescription,
imageHeight, ImageHeight: imageHeight,
imageNumber, ImageHeightValue: imageHeightValue,
imageUniqueId, ImageNumber: imageNumber,
imageWidth, ImageUniqueId: imageUniqueId,
isoSpeed, ImageWidth: imageWidth,
lensMake, ImageWidthValue: imageWidthValue,
lensModel, IsoSpeed: isoSpeed,
lensSerialNumber, LensMake: lensMake,
make, LensModel: lensModel,
makerNote, LensSerialNumber: lensSerialNumber,
model, Make: make,
orientation, MakerNote: makerNote,
orientationValue, Model: model,
rating, Orientation: orientation,
ratingPercent, OrientationValue: orientationValue,
securityClassification, Rating: rating,
shutterSpeed, RatingPercent: ratingPercent,
software, SecurityClassification: securityClassification,
timeZone, ShutterSpeed: shutterSpeed,
timeZoneDigitized, Software: software,
timeZoneOriginal, TimeZone: timeZone,
userComment, TimeZoneDigitized: timeZoneDigitized,
winAuthor, TimeZoneOriginal: timeZoneOriginal,
winComment, UserComment: userComment,
winKeywords, WinAuthor: winAuthor,
winSubject, WinComment: winComment,
winTitle, WinKeywords: winKeywords,
xResolution, WinSubject: winSubject,
yResolution); WinTitle: winTitle,
XResolution: xResolution,
YResolution: yResolution);
results.Add(exifDirectoryBase); results.Add(exifDirectoryBase);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.FileMetadataDirectory[] GetFileMetadataDirectories(string file, IReadOnlyList<MetadataExtractor.Directory> directories) private static FileMetadataDirectory[] GetFileMetadataDirectories(string file, IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.FileMetadataDirectory> results = []; List<FileMetadataDirectory> results = [];
Shared.Models.FileMetadataDirectory fileMetadataDirectory; FileMetadataDirectory fileMetadataDirectory;
IEnumerable<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory> fileMetadataDirectories = directories.OfType<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory>(); IEnumerable<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory> fileMetadataDirectories = directories.OfType<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory>();
foreach (MetadataExtractor.Formats.FileSystem.FileMetadataDirectory f in fileMetadataDirectories) foreach (MetadataExtractor.Formats.FileSystem.FileMetadataDirectory f in fileMetadataDirectories)
{ {
@ -237,16 +242,16 @@ internal abstract class Exif
throw new NotSupportedException($"!{file}.EndsWith({fileName})"); throw new NotSupportedException($"!{file}.EndsWith({fileName})");
if (fileModifiedDate is null && fileName is null && fileSize is null) if (fileModifiedDate is null && fileName is null && fileSize is null)
continue; continue;
fileMetadataDirectory = new(fileModifiedDate, fileName, fileSize); fileMetadataDirectory = new(FileModifiedDate: fileModifiedDate, FileName: fileName, FileSize: fileSize);
results.Add(fileMetadataDirectory); results.Add(fileMetadataDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.GifHeaderDirectory[] GetGifHeaderDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static GifHeaderDirectory[] GetGifHeaderDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.GifHeaderDirectory> results = []; List<GifHeaderDirectory> results = [];
Shared.Models.GifHeaderDirectory gifHeaderDirectory; GifHeaderDirectory gifHeaderDirectory;
IEnumerable<MetadataExtractor.Formats.Gif.GifHeaderDirectory> gifHeaderDirectories = directories.OfType<MetadataExtractor.Formats.Gif.GifHeaderDirectory>(); IEnumerable<MetadataExtractor.Formats.Gif.GifHeaderDirectory> gifHeaderDirectories = directories.OfType<MetadataExtractor.Formats.Gif.GifHeaderDirectory>();
foreach (MetadataExtractor.Formats.Gif.GifHeaderDirectory g in gifHeaderDirectories) foreach (MetadataExtractor.Formats.Gif.GifHeaderDirectory g in gifHeaderDirectories)
{ {
@ -256,48 +261,48 @@ internal abstract class Exif
string? imageWidth = g.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth); string? imageWidth = g.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth);
if (imageHeight is null && imageWidth is null) if (imageHeight is null && imageWidth is null)
continue; continue;
gifHeaderDirectory = new(imageHeight, imageWidth); gifHeaderDirectory = new(ImageHeight: imageHeight, ImageWidth: imageWidth);
results.Add(gifHeaderDirectory); results.Add(gifHeaderDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.GpsDirectory[] GetGpsDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static GpsDirectory[] GetGpsDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.GpsDirectory> results = []; List<GpsDirectory> results = [];
Shared.Models.GpsDirectory gpsDirectory; GpsDirectory gpsDirectory;
IEnumerable<GpsDirectory> gpsDirectories = directories.OfType<GpsDirectory>(); IEnumerable<MetadataExtractor.Formats.Exif.GpsDirectory> gpsDirectories = directories.OfType<MetadataExtractor.Formats.Exif.GpsDirectory>();
foreach (GpsDirectory g in gpsDirectories) foreach (MetadataExtractor.Formats.Exif.GpsDirectory g in gpsDirectories)
{ {
if (g.Tags.Count == 0) if (g.Tags.Count == 0)
continue; continue;
DateTime? timeStamp; DateTime? timeStamp;
string? altitude = g.GetDescription(GpsDirectory.TagAltitude); string? altitude = g.GetDescription(MetadataExtractor.Formats.Exif.GpsDirectory.TagAltitude);
string? latitude = g.GetDescription(GpsDirectory.TagLatitude); string? latitude = g.GetDescription(MetadataExtractor.Formats.Exif.GpsDirectory.TagLatitude);
string? latitudeRef = g.GetDescription(GpsDirectory.TagLatitudeRef); string? latitudeRef = g.GetDescription(MetadataExtractor.Formats.Exif.GpsDirectory.TagLatitudeRef);
string? longitude = g.GetDescription(GpsDirectory.TagLongitude); string? longitude = g.GetDescription(MetadataExtractor.Formats.Exif.GpsDirectory.TagLongitude);
string? longitudeRef = g.GetDescription(GpsDirectory.TagLongitudeRef); string? longitudeRef = g.GetDescription(MetadataExtractor.Formats.Exif.GpsDirectory.TagLongitudeRef);
if (g.TryGetDateTime(GpsDirectory.TagTimeStamp, out DateTime checkDateTime)) if (g.TryGetDateTime(MetadataExtractor.Formats.Exif.GpsDirectory.TagTimeStamp, out DateTime checkDateTime))
timeStamp = checkDateTime; timeStamp = checkDateTime;
else else
timeStamp = GetDateTime(g.GetString(GpsDirectory.TagTimeStamp)); timeStamp = GetDateTime(g.GetString(MetadataExtractor.Formats.Exif.GpsDirectory.TagTimeStamp));
if (altitude is null && latitude is null && latitudeRef is null && longitude is null && longitudeRef is null && timeStamp is null) if (altitude is null && latitude is null && latitudeRef is null && longitude is null && longitudeRef is null && timeStamp is null)
continue; continue;
gpsDirectory = new(altitude, gpsDirectory = new(Altitude: altitude,
latitude, Latitude: latitude,
latitudeRef, LatitudeRef: latitudeRef,
longitude, Longitude: longitude,
longitudeRef, LongitudeRef: longitudeRef,
timeStamp); TimeStamp: timeStamp);
results.Add(gpsDirectory); results.Add(gpsDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.JpegDirectory[] GetJpegDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static JpegDirectory[] GetJpegDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.JpegDirectory> results = []; List<JpegDirectory> results = [];
Shared.Models.JpegDirectory jpegDirectory; JpegDirectory jpegDirectory;
IEnumerable<MetadataExtractor.Formats.Jpeg.JpegDirectory> jpegDirectories = directories.OfType<MetadataExtractor.Formats.Jpeg.JpegDirectory>(); IEnumerable<MetadataExtractor.Formats.Jpeg.JpegDirectory> jpegDirectories = directories.OfType<MetadataExtractor.Formats.Jpeg.JpegDirectory>();
foreach (MetadataExtractor.Formats.Jpeg.JpegDirectory j in jpegDirectories) foreach (MetadataExtractor.Formats.Jpeg.JpegDirectory j in jpegDirectories)
{ {
@ -307,16 +312,16 @@ internal abstract class Exif
string? imageWidth = j.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth); string? imageWidth = j.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth);
if (imageHeight is null && imageWidth is null) if (imageHeight is null && imageWidth is null)
continue; continue;
jpegDirectory = new(imageHeight, imageWidth); jpegDirectory = new(ImageHeight: imageHeight, ImageWidth: imageWidth);
results.Add(jpegDirectory); results.Add(jpegDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.MakernoteDirectory[] GetMakernoteDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static MakernoteDirectory[] GetMakernoteDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.MakernoteDirectory> results = []; List<MakernoteDirectory> results = [];
Shared.Models.MakernoteDirectory makernoteDirectory; MakernoteDirectory makernoteDirectory;
IEnumerable<AppleMakernoteDirectory> appleMakernoteDirectories = directories.OfType<AppleMakernoteDirectory>(); IEnumerable<AppleMakernoteDirectory> appleMakernoteDirectories = directories.OfType<AppleMakernoteDirectory>();
foreach (AppleMakernoteDirectory appleMakernoteDirectory in appleMakernoteDirectories) foreach (AppleMakernoteDirectory appleMakernoteDirectory in appleMakernoteDirectories)
{ {
@ -405,16 +410,16 @@ internal abstract class Exif
string? qualityAndFileFormat = null; string? qualityAndFileFormat = null;
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
continue; continue;
makernoteDirectory = new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat); makernoteDirectory = new(CameraSerialNumber: cameraSerialNumber, FirmwareVersion: firmwareVersion, QualityAndFileFormat: qualityAndFileFormat);
results.Add(makernoteDirectory); results.Add(makernoteDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.PhotoshopDirectory[] GetPhotoshopDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static PhotoshopDirectory[] GetPhotoshopDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.PhotoshopDirectory> results = []; List<PhotoshopDirectory> results = [];
Shared.Models.PhotoshopDirectory photoshopDirectory; PhotoshopDirectory photoshopDirectory;
IEnumerable<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory> photoshopDirectories = directories.OfType<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory>(); IEnumerable<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory> photoshopDirectories = directories.OfType<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory>();
foreach (MetadataExtractor.Formats.Photoshop.PhotoshopDirectory p in photoshopDirectories) foreach (MetadataExtractor.Formats.Photoshop.PhotoshopDirectory p in photoshopDirectories)
{ {
@ -424,16 +429,16 @@ internal abstract class Exif
string? url = p.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl); string? url = p.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl);
if (jpegQuality is null && url is null) if (jpegQuality is null && url is null)
continue; continue;
photoshopDirectory = new(jpegQuality, url); photoshopDirectory = new(JpegQuality: jpegQuality, Url: url);
results.Add(photoshopDirectory); results.Add(photoshopDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.PngDirectory[] GetPngDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static PngDirectory[] GetPngDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.PngDirectory> results = []; List<PngDirectory> results = [];
Shared.Models.PngDirectory pngDirectory; PngDirectory pngDirectory;
IEnumerable<MetadataExtractor.Formats.Png.PngDirectory> pngDirectories = directories.OfType<MetadataExtractor.Formats.Png.PngDirectory>(); IEnumerable<MetadataExtractor.Formats.Png.PngDirectory> pngDirectories = directories.OfType<MetadataExtractor.Formats.Png.PngDirectory>();
foreach (MetadataExtractor.Formats.Png.PngDirectory p in pngDirectories) foreach (MetadataExtractor.Formats.Png.PngDirectory p in pngDirectories)
{ {
@ -444,16 +449,16 @@ internal abstract class Exif
string? textualData = p.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagTextualData); string? textualData = p.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagTextualData);
if (imageHeight is null && imageWidth is null && textualData is null) if (imageHeight is null && imageWidth is null && textualData is null)
continue; continue;
pngDirectory = new(imageHeight, imageWidth, textualData); pngDirectory = new(ImageHeight: imageHeight, ImageWidth: imageWidth, TextualData: textualData);
results.Add(pngDirectory); results.Add(pngDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.QuickTimeMovieHeaderDirectory[] GetQuickTimeMovieHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static QuickTimeMovieHeaderDirectory[] GetQuickTimeMovieHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.QuickTimeMovieHeaderDirectory> results = []; List<QuickTimeMovieHeaderDirectory> results = [];
Shared.Models.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory; QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory;
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory> quickTimeMovieHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory>(); IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory> quickTimeMovieHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory>();
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory q in quickTimeMovieHeaderDirectories) foreach (MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory q in quickTimeMovieHeaderDirectories)
{ {
@ -466,16 +471,16 @@ internal abstract class Exif
created = GetDateTime(q.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated)); created = GetDateTime(q.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated));
if (created is null) if (created is null)
continue; continue;
quickTimeMovieHeaderDirectory = new(created); quickTimeMovieHeaderDirectory = new(Created: created);
results.Add(quickTimeMovieHeaderDirectory); results.Add(quickTimeMovieHeaderDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.QuickTimeTrackHeaderDirectory[] GetQuickTimeTrackHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static QuickTimeTrackHeaderDirectory[] GetQuickTimeTrackHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.QuickTimeTrackHeaderDirectory> results = []; List<QuickTimeTrackHeaderDirectory> results = [];
Shared.Models.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory; QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory;
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory> quickTimeTrackHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory>(); IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory> quickTimeTrackHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory>();
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory q in quickTimeTrackHeaderDirectories) foreach (MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory q in quickTimeTrackHeaderDirectories)
{ {
@ -488,16 +493,16 @@ internal abstract class Exif
created = GetDateTime(q.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated)); created = GetDateTime(q.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated));
if (created is null) if (created is null)
continue; continue;
quickTimeTrackHeaderDirectory = new(created); quickTimeTrackHeaderDirectory = new(Created: created);
results.Add(quickTimeTrackHeaderDirectory); results.Add(quickTimeTrackHeaderDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.WebPDirectory[] GetWebPDirectories(IReadOnlyList<MetadataExtractor.Directory> directories) private static WebPDirectory[] GetWebPDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
List<Shared.Models.WebPDirectory> results = []; List<WebPDirectory> results = [];
Shared.Models.WebPDirectory webPDirectory; WebPDirectory webPDirectory;
IEnumerable<MetadataExtractor.Formats.WebP.WebPDirectory> webPDirectories = directories.OfType<MetadataExtractor.Formats.WebP.WebPDirectory>(); IEnumerable<MetadataExtractor.Formats.WebP.WebPDirectory> webPDirectories = directories.OfType<MetadataExtractor.Formats.WebP.WebPDirectory>();
foreach (MetadataExtractor.Formats.WebP.WebPDirectory w in webPDirectories) foreach (MetadataExtractor.Formats.WebP.WebPDirectory w in webPDirectories)
{ {
@ -507,63 +512,68 @@ internal abstract class Exif
string? imageWidth = w.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth); string? imageWidth = w.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth);
if (imageHeight is null && imageWidth is null) if (imageHeight is null && imageWidth is null)
continue; continue;
webPDirectory = new(imageHeight, imageWidth); webPDirectory = new(ImageHeight: imageHeight, ImageWidth: imageWidth);
results.Add(webPDirectory); results.Add(webPDirectory);
} }
return results.ToArray(); return results.ToArray();
} }
private static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, Shared.Models.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName, IReadOnlyList<MetadataExtractor.Directory> directories, System.Drawing.Size? size) private static ExifDirectory Covert(FilePath filePath, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName, IReadOnlyList<MetadataExtractor.Directory> directories, System.Drawing.Size? size)
{ {
Shared.Models.ExifDirectory result; ExifDirectory result;
Shared.Models.AviDirectory[] aviDirectories = GetAviDirectories(directories); AviDirectory[] aviDirectories = GetAviDirectories(directories);
Shared.Models.GpsDirectory[] gpsDirectories = GetGpsDirectories(directories); GpsDirectory[] gpsDirectories = GetGpsDirectories(directories);
Shared.Models.PngDirectory[] pngDirectories = GetPngDirectories(directories); PngDirectory[] pngDirectories = GetPngDirectories(directories);
Shared.Models.JpegDirectory[] jpegDirectories = GetJpegDirectories(directories); JpegDirectory[] jpegDirectories = GetJpegDirectories(directories);
Shared.Models.WebPDirectory[] webPDirectories = GetWebPDirectories(directories); WebPDirectory[] webPDirectories = GetWebPDirectories(directories);
Shared.Models.ExifDirectoryBase[] exifBaseDirectories = GetExifBaseDirectories(directories); ExifDirectoryBase[] exifBaseDirectories = GetExifBaseDirectories(directories);
Shared.Models.GifHeaderDirectory[] gifHeaderDirectories = GetGifHeaderDirectories(directories); GifHeaderDirectory[] gifHeaderDirectories = GetGifHeaderDirectories(directories);
Shared.Models.MakernoteDirectory[] MakernoteDirectories = GetMakernoteDirectories(directories); MakernoteDirectory[] makernoteDirectories = GetMakernoteDirectories(directories);
Shared.Models.PhotoshopDirectory[] photoshopDirectories = GetPhotoshopDirectories(directories); PhotoshopDirectory[] photoshopDirectories = GetPhotoshopDirectories(directories);
Shared.Models.FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(filePath.FullName, directories); FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(filePath.FullName, directories);
Shared.Models.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories); QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories);
Shared.Models.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories); QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories);
result = new(aviDirectories, result = new(AviDirectories: aviDirectories,
null, ExifBaseDirectories: exifBaseDirectories,
exifBaseDirectories, FileMetadataDirectories: fileMetadataDirectories,
fileMetadataDirectories, FilePath: filePath,
filePath, GifHeaderDirectories: gifHeaderDirectories,
gifHeaderDirectories, GpsDirectories: gpsDirectories,
gpsDirectories, Height: size?.Height ?? IMetaBase.GetHeight(exifBaseDirectories),
size?.Height, JpegDirectories: jpegDirectories,
jpegDirectories, MakernoteDirectories: makernoteDirectories,
MakernoteDirectories, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: personKeyFormattedAndKeyTicksAndDisplayDirectoryName,
personKeyFormattedAndKeyTicksAndDisplayDirectoryName, PhotoshopDirectories: photoshopDirectories,
photoshopDirectories, PngDirectories: pngDirectories,
pngDirectories, QuickTimeMovieHeaderDirectories: quickTimeMovieHeaderDirectories,
quickTimeMovieHeaderDirectories, QuickTimeTrackHeaderDirectories: quickTimeTrackHeaderDirectories,
quickTimeTrackHeaderDirectories, WebPDirectories: webPDirectories,
webPDirectories, Width: size?.Width ?? IMetaBase.GetWidth(exifBaseDirectories));
size?.Width);
return result; return result;
} }
internal static Shared.Models.ExifDirectory GetExifDirectory(Shared.Models.FilePath filePath, Stream stream, Shared.Models.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) internal static ExifDirectory GetExifDirectory(FilePath filePath, Stream stream, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName)
{ {
Shared.Models.ExifDirectory result; ExifDirectory result;
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(stream); IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(stream);
System.Drawing.Size? size; System.Drawing.Size? size;
if (!stream.CanSeek) try
size = null; { size = Dimensions.GetDimensions(stream); }
else catch (Exception)
{ { size = null; }
try
{ size = Dimensions.GetDimensions(stream); }
catch (Exception)
{ size = null; }
}
result = Covert(filePath, personKeyFormattedAndKeyTicksAndDisplayDirectoryName, directories, size); result = Covert(filePath, personKeyFormattedAndKeyTicksAndDisplayDirectoryName, directories, size);
return result; return result;
} }
internal static ExifDirectory? GetExifDirectory(ResultSettings resultSettings, MetadataSettings metadataSettings, FileInfo fileInfo)
{
ExifDirectory? result;
FileHolder fileHolder = FileHolder.Get(fileInfo, id: null);
const PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? p = null;
FilePath filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: fileHolder.Id);
using Stream stream = File.OpenRead(filePath.FullName);
result = GetExifDirectory(filePath, stream, p);
return result;
}
} }

View File

@ -1,10 +1,19 @@
using View_by_Distance.Shared.Models; using System.Text.Json;
using Phares.Shared.Models;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
internal static class Face internal static class Face
{ {
internal static FaceEncoding? GetFaceEncoding(ExifDirectory? exifDirectory)
{
FaceEncoding? result;
string? json = GetFaceEncoding(exifDirectory?.PngDirectories);
result = string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize(json, FaceEncodingGenerationContext.Default.FaceEncoding);
return result;
}
internal static string? GetFaceEncoding(PngDirectory[]? pngDirectories) internal static string? GetFaceEncoding(PngDirectory[]? pngDirectories)
{ {
string? result = null; string? result = null;
@ -22,7 +31,15 @@ internal static class Face
return result; return result;
} }
internal static string? GetOutputResolution(PngDirectory[]? pngDirectories) internal static FaceFile? GetFaceFile(ExifDirectory? exifDirectory)
{
FaceFile? result;
string? json = GetOutputResolution(exifDirectory?.PngDirectories);
result = string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize(json, FaceFileGenerationContext.Default.FaceFile);
return result;
}
private static string? GetOutputResolution(PngDirectory[]? pngDirectories)
{ {
string? result = null; string? result = null;
if (pngDirectories is not null) if (pngDirectories is not null)

View File

@ -1,8 +1,7 @@
using MetadataExtractor; using MetadataExtractor;
using View_by_Distance.Metadata.Models.Stateless; using Phares.Shared.Models;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
internal abstract class GPS internal abstract class GPS
{ {

View File

@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
internal static class Get internal static class Get
{ {

View File

@ -1,10 +1,10 @@
using MetadataExtractor; using MetadataExtractor;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models.Stateless; namespace Phares.Metadata.Models.Stateless;
public interface IMetadata public interface IMetadata
{ {
@ -17,64 +17,70 @@ public interface IMetadata
Meters Meters
} }
ExifDirectory TestStatic_GetExifDirectory(FilePath filePath, Stream stream, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) => public static FaceFile? GetFaceFile(ExifDirectory? exifDirectory) =>
GetExifDirectory(filePath, stream, personKeyFormattedAndKeyTicksAndDisplayDirectoryName); Face.GetFaceFile(exifDirectory);
static ExifDirectory GetExifDirectory(FilePath filePath, Stream stream, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) =>
Exif.GetExifDirectory(filePath, stream, personKeyFormattedAndKeyTicksAndDisplayDirectoryName);
string? TestStatic_GetMaker(ExifDirectory? exifDirectory) => public static GeoLocation? GeoLocation(ExifDirectory? exifDirectory) =>
GetMaker(exifDirectory);
static string? GetMaker(ExifDirectory? exifDirectory) =>
Base.GetMaker(exifDirectory?.ExifBaseDirectories);
string? TestStatic_GetModel(ExifDirectory? exifDirectory) =>
GetModel(exifDirectory);
static string? GetModel(ExifDirectory? exifDirectory) =>
Base.GetModel(exifDirectory?.ExifBaseDirectories);
ReadOnlyCollection<string> TestStatic_GetKeywords(ExifDirectory? exifDirectory) =>
GetKeywords(exifDirectory);
static ReadOnlyCollection<string> GetKeywords(ExifDirectory? exifDirectory) =>
Base.GetKeywords(exifDirectory?.ExifBaseDirectories);
string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) =>
GetOutputResolution(exifDirectory);
static string? GetOutputResolution(ExifDirectory? exifDirectory) =>
Face.GetOutputResolution(exifDirectory?.PngDirectories);
string? TestStatic_GetFaceEncoding(ExifDirectory? exifDirectory) =>
GetFaceEncoding(exifDirectory);
static string? GetFaceEncoding(ExifDirectory? exifDirectory) =>
Face.GetFaceEncoding(exifDirectory?.PngDirectories);
GeoLocation? TestStatic_GeoLocation(ExifDirectory? exifDirectory) =>
GeoLocation(exifDirectory);
static GeoLocation? GeoLocation(ExifDirectory? exifDirectory) =>
GPS.GeoLocation(exifDirectory?.GpsDirectories); GPS.GeoLocation(exifDirectory?.GpsDirectories);
double? TestStatic_GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) => public static string? GetRawFaceEncoding(ExifDirectory? exifDirectory) =>
GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit); Face.GetFaceEncoding(exifDirectory?.PngDirectories);
static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>
GPS.GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
Action<string> TestStatic_SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) => public static FaceEncoding? GetFaceEncoding(ExifDirectory? exifDirectory) =>
SetExifDirectoryCollection(rename, resultSettings, metadataSettings, renameSettings, metadata, distinct, metadataGroups); Face.GetFaceEncoding(exifDirectory);
static Action<string> SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
Get.SetExifDirectoryCollection(rename, resultSettings, metadataSettings, renameSettings, metadata, distinct, metadataGroups);
ReadOnlyDictionary<string, List<FileHolder>> TestStatic_GetKeyValuePairs(IEnumerable<string> files) => public static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<string> files) =>
GetKeyValuePairs(files);
static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<string> files) =>
Get.GetKeyValuePairs(files); Get.GetKeyValuePairs(files);
ReadOnlyDictionary<string, List<FileHolder>> TestStatic_GetKeyValuePairs(IEnumerable<NginxFileSystem> collection) => public static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<NginxFileSystem> collection) =>
GetKeyValuePairs(collection);
static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<NginxFileSystem> collection) =>
Get.GetKeyValuePairs(collection); Get.GetKeyValuePairs(collection);
Action<string> TestStatic_SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) => public static ExifDirectory? GetExifDirectory(ResultSettings resultSettings, MetadataSettings metadataSettings, FileInfo fileInfo) =>
SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups); Exif.GetExifDirectory(resultSettings, metadataSettings, fileInfo);
static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
public static ExifDirectory GetExifDirectory(FilePath filePath, Stream stream, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) =>
Exif.GetExifDirectory(filePath, stream, personKeyFormattedAndKeyTicksAndDisplayDirectoryName);
public static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>
GPS.GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
public static Action<string> SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
Get.SetExifDirectoryCollection(rename, resultSettings, metadataSettings, renameSettings, metadata, distinct, metadataGroups);
public static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
Get.SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups); Get.SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups);
internal GeoLocation? TestStatic_GeoLocation(ExifDirectory? exifDirectory) =>
GeoLocation(exifDirectory);
internal string? TestStatic_GetRawFaceEncoding(ExifDirectory? exifDirectory) =>
GetRawFaceEncoding(exifDirectory);
internal static FaceFile? TestStatic_GetFaceFile(ExifDirectory? exifDirectory) =>
GetFaceFile(exifDirectory);
internal static FaceEncoding? TestStatic_GetFaceEncoding(ExifDirectory? exifDirectory) =>
GetFaceEncoding(exifDirectory);
internal ReadOnlyDictionary<string, List<FileHolder>> TestStatic_GetKeyValuePairs(IEnumerable<string> files) =>
GetKeyValuePairs(files);
internal ReadOnlyDictionary<string, List<FileHolder>> TestStatic_GetKeyValuePairs(IEnumerable<NginxFileSystem> collection) =>
GetKeyValuePairs(collection);
internal ExifDirectory? TestStatic_GetExifDirectory(ResultSettings resultSettings, MetadataSettings metadataSettings, FileInfo fileInfo) =>
GetExifDirectory(resultSettings, metadataSettings, fileInfo);
internal ExifDirectory TestStatic_GetExifDirectory(FilePath filePath, Stream stream, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? personKeyFormattedAndKeyTicksAndDisplayDirectoryName) =>
GetExifDirectory(filePath, stream, personKeyFormattedAndKeyTicksAndDisplayDirectoryName);
internal 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);
internal Action<string> TestStatic_SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
SetExifDirectoryCollection(windows, resultSettings, metadataSettings, metadata, distinct, metadataGroups);
internal Action<string> TestStatic_SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups) =>
SetExifDirectoryCollection(rename, resultSettings, metadataSettings, renameSettings, metadata, distinct, metadataGroups);
} }

View File

@ -10,7 +10,7 @@
<HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024> <HoursSinceNovember122024>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</HoursSinceNovember122024>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.People</PackageId> <PackageId>Phares.People</PackageId>
<Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version> <Version>9.0.104.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1731369600)), 3600))))</Version>
<Company>Phares</Company> <Company>Phares</Company>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>

View File

@ -1,3 +1,3 @@
namespace View_by_Distance.Metadata.Models; namespace Phares.Metadata.Models;
public class A2_People() { } public class A2_People() { }

View File

@ -1,6 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
namespace View_by_Distance.People.Models.Stateless; namespace View_by_Distance.People.Models.Stateless;

View File

@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Globalization; using System.Globalization;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
using WindowsShortcutFactory; using WindowsShortcutFactory;
namespace View_by_Distance.People.Models.Stateless; namespace View_by_Distance.People.Models.Stateless;

View File

@ -1,8 +1,8 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using View_by_Distance.Metadata.Models; using Phares.Metadata.Models;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using Phares.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.People.Models.Stateless; namespace View_by_Distance.People.Models.Stateless;

View File

@ -1,7 +1,7 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models; using Phares.Shared.Models;
namespace View_by_Distance.Rename.Models; namespace View_by_Distance.Rename.Models;

View File

@ -1,4 +1,5 @@
using Phares.Shared.Models.Properties;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -19,7 +20,9 @@ public record RenameSettings(string Company,
string RelativePropertyCollectionFile, string RelativePropertyCollectionFile,
bool RequireRootDirectoryExists, bool RequireRootDirectoryExists,
string[] SidecarExtensions, string[] SidecarExtensions,
bool SkipIdFiles) : Shared.Models.Properties.IRenameSettings bool SkipIdFiles,
int ValidationImageDeterministicHashCodeId,
string ValidationImageFile) : IRenameSettings
{ {
public override string ToString() public override string ToString()

View File

@ -23,7 +23,7 @@ public class Program
{ {
if (args is null) if (args is null)
throw new Exception("args is null!"); throw new Exception("args is null!");
Shared.Models.Console console = new(); Phares.Shared.Models.Console console = new();
_ = new Rename(args, logger, appSettings, silentIndex > -1, console); _ = new Rename(args, logger, appSettings, silentIndex > -1, console);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,5 +1,9 @@
using CliWrap; using CliWrap;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Phares.Metadata.Models;
using Phares.Metadata.Models.Stateless;
using Phares.Shared.Models;
using Phares.Shared.Models.Stateless;
using ShellProgressBar; using ShellProgressBar;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Data; using System.Data;
@ -7,17 +11,16 @@ using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Rename.Models; using View_by_Distance.Rename.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Rename; namespace View_by_Distance.Rename;
public partial class Rename : IRename, IDisposable public partial class Rename : IRename, IDisposable
{ {
public long Ticks { get; init; }
public int? CurrentTick => _ProgressBar?.CurrentTick;
private sealed record ToDo(string? Directory, private sealed record ToDo(string? Directory,
FileInfo FileInfo, FileInfo FileInfo,
string File, string File,
@ -124,23 +127,58 @@ public partial class Rename : IRename, IDisposable
if (console is null) if (console is null)
throw new NullReferenceException(nameof(console)); throw new NullReferenceException(nameof(console));
IRename rename = this; IRename rename = this;
long ticks = DateTime.Now.Ticks; LogNetToHoursSince(logger);
Ticks = DateTime.Now.Ticks;
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; _ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
RenameWork(logger, appSettings, rename, ticks); Verify(logger, appSettings, rename);
RenameWork(logger, appSettings, rename);
} }
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks) private static void Verify(ILogger<Program>? logger, AppSettings appSettings, IRename rename)
{
FileHolder fileHolder = FileHolder.Get(appSettings.RenameSettings.ValidationImageFile);
FilePath filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, index: null);
DeterministicHashCode deterministicHashCode = rename.GetDeterministicHashCode(filePath);
if (deterministicHashCode.Id is null)
throw new NullReferenceException(nameof(deterministicHashCode));
if (deterministicHashCode.Id.Value != appSettings.RenameSettings.ValidationImageDeterministicHashCodeId)
throw new Exception("Deterministic hash code id is incorrect!");
logger?.LogDebug("Validated deterministic hash code id");
}
private static void LogNetToHoursSince(ILogger<Program>? logger)
{
double secondsInAHour = 3600f;
long epoch = new DateTime(1970, 1, 1).Ticks;
long net8ReleaseDate = new DateTime(2023, 11, 14).Ticks;
long net9ReleaseDate = new DateTime(2024, 11, 12).Ticks;
long net10ReleaseDate = new DateTime(2026, 01, 01).Ticks;
double net8TotalSeconds = new TimeSpan(net8ReleaseDate - epoch).TotalSeconds;
double net9TotalSeconds = new TimeSpan(net9ReleaseDate - epoch).TotalSeconds;
double net10TotalSeconds = new TimeSpan(net10ReleaseDate - epoch).TotalSeconds;
logger?.LogInformation("It has been {net8TotalSeconds} seconds since net8 was released", net8TotalSeconds);
logger?.LogInformation("It has been {net9TotalSeconds} seconds since net9 was released", net9TotalSeconds);
logger?.LogInformation("It has been {net10TotalSeconds} seconds since net10 was released", net10TotalSeconds);
double net8TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net8TotalSeconds) / secondsInAHour);
double net9TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net9TotalSeconds) / secondsInAHour);
double net10TotalHours = Math.Floor((DateTimeOffset.UtcNow.ToUnixTimeSeconds() - net10TotalSeconds) / secondsInAHour);
logger?.LogInformation("It has been {net8TotalHours} hours since net8 was released", net8TotalHours);
logger?.LogInformation("It has been {net9TotalHours} hours since net9 was released", net9TotalHours);
logger?.LogInformation("It has been {net10TotalHours} hours since net10 was released", net10TotalHours);
}
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename)
{ {
ReadOnlyCollection<int> ids = GetIds(appSettings.RenameSettings); ReadOnlyCollection<int> ids = GetIds(appSettings.RenameSettings);
string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory); string sourceDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
if (!Directory.Exists(sourceDirectory)) if (!Directory.Exists(sourceDirectory))
_ = Directory.CreateDirectory(sourceDirectory); _ = Directory.CreateDirectory(sourceDirectory);
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory); logger?.LogInformation("{Ticks} {RootDirectory}", rename.Ticks, sourceDirectory);
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly(); ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray().AsReadOnly();
if (files.Count > 0) if (files.Count > 0)
_ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory); _ = IPath.DeleteEmptyDirectories(appSettings.ResultSettings.RootDirectory);
ReadOnlyCollection<Record> recordCollection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files); ReadOnlyCollection<Record> recordCollection = GetRecordCollection(logger, appSettings, rename, ids, sourceDirectory, files);
SaveIdentifiersToDisk(ticks, appSettings, recordCollection); SaveIdentifiersToDisk(appSettings, rename, recordCollection);
if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName) if (appSettings.RenameSettings.InPlace || appSettings.RenameSettings.InPlaceWithOriginalName)
{ {
if (recordCollection.Count > 0) if (recordCollection.Count > 0)
@ -173,13 +211,13 @@ public partial class Rename : IRename, IDisposable
return results; return results;
} }
private ReadOnlyCollection<Record> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files) private ReadOnlyCollection<Record> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files)
{ {
ReadOnlyCollection<Record> results; ReadOnlyCollection<Record> results;
List<FirstPass> collection; List<FirstPass> collection;
string? checkFile = string.IsNullOrEmpty(appSettings.RenameSettings.FirstPassFile) ? null : Path.Combine(sourceDirectory, appSettings.RenameSettings.FirstPassFile); string? checkFile = string.IsNullOrEmpty(appSettings.RenameSettings.FirstPassFile) ? null : Path.Combine(sourceDirectory, appSettings.RenameSettings.FirstPassFile);
if (string.IsNullOrEmpty(checkFile) || !File.Exists(checkFile)) if (string.IsNullOrEmpty(checkFile) || !File.Exists(checkFile))
collection = GetRecordCollection(logger, appSettings, rename, ticks, ids, sourceDirectory, files, checkFile); collection = GetRecordCollection(logger, appSettings, rename, ids, sourceDirectory, files, checkFile);
else else
{ {
string json = File.ReadAllText(checkFile); string json = File.ReadAllText(checkFile);
@ -192,7 +230,7 @@ public partial class Rename : IRename, IDisposable
return results; return results;
} }
private List<FirstPass> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files, string? checkFile) private List<FirstPass> GetRecordCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, string sourceDirectory, ReadOnlyCollection<string> files, string? checkFile)
{ {
List<FirstPass> results; List<FirstPass> results;
FirstPass firstPass; FirstPass firstPass;
@ -203,7 +241,7 @@ public partial class Rename : IRename, IDisposable
if (appSettingsMaxDegreeOfParallelism == 1) if (appSettingsMaxDegreeOfParallelism == 1)
{ {
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs = IMetadata.GetKeyValuePairs(files); ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs = IMetadata.GetKeyValuePairs(files);
results = GetFirstPassCollection(logger, appSettings, rename, ticks, ids, metadata, keyValuePairs); results = GetFirstPassCollection(logger, appSettings, rename, ids, metadata, keyValuePairs);
} }
else else
{ {
@ -225,13 +263,13 @@ public partial class Rename : IRename, IDisposable
if (!string.IsNullOrEmpty(checkFile)) if (!string.IsNullOrEmpty(checkFile))
{ {
string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass); string json = JsonSerializer.Serialize(results, FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
File.WriteAllText(Path.Combine(sourceDirectory, $"{ticks}.json"), json); File.WriteAllText(Path.Combine(sourceDirectory, $"{rename.Ticks}.json"), json);
} }
return results; return results;
} }
private List<FirstPass> GetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, ReadOnlyCollection<int> ids, A_Metadata metadata, ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs) private List<FirstPass> GetFirstPassCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, A_Metadata metadata, ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs)
{ {
List<FirstPass> results = []; List<FirstPass> results = [];
int index = -1; int index = -1;
@ -249,7 +287,7 @@ public partial class Rename : IRename, IDisposable
if (keyValuePair.Value.Count > 2) if (keyValuePair.Value.Count > 2)
throw new NotSupportedException("Too many sidecar files!"); throw new NotSupportedException("Too many sidecar files!");
SetFirstPassCollection(logger, appSettings, rename, ids, metadata, index, keyValuePair, results); SetFirstPassCollection(logger, appSettings, rename, ids, metadata, index, keyValuePair, results);
timeSpan = new(DateTime.Now.Ticks - ticks); timeSpan = new(DateTime.Now.Ticks - rename.Ticks);
if (timeSpan.TotalMilliseconds > appSettings.RenameSettings.MaxMilliSecondsPerCall) if (timeSpan.TotalMilliseconds > appSettings.RenameSettings.MaxMilliSecondsPerCall)
break; break;
} }
@ -361,11 +399,11 @@ public partial class Rename : IRename, IDisposable
const string jpeg = ".jpeg"; const string jpeg = ".jpeg";
List<ToDo> toDoCollection = []; List<ToDo> toDoCollection = [];
DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory); DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
ReadOnlyCollection<string> keywords = IMetadata.GetKeywords(exifDirectory); ReadOnlyCollection<string> keywords = IMetaBase.GetKeywords(exifDirectory);
bool hasIgnoreKeyword = appSettings.MetadataSettings.IgnoreRulesKeyWords.Any(keywords.Contains); bool hasIgnoreKeyword = appSettings.MetadataSettings.IgnoreRulesKeyWords.Any(keywords.Contains);
string checkFileExtension = exifDirectory.FilePath.ExtensionLowered == jpeg ? jpg : exifDirectory.FilePath.ExtensionLowered; string checkFileExtension = exifDirectory.FilePath.ExtensionLowered == jpeg ? jpg : exifDirectory.FilePath.ExtensionLowered;
bool hasDateTimeOriginal = dateTime is not null; bool hasDateTimeOriginal = dateTime is not null;
string paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, exifDirectory.FilePath.Id.Value, hasIgnoreKeyword, hasDateTimeOriginal, i); string paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, exifDirectory.FilePath, hasIgnoreKeyword, hasDateTimeOriginal, i);
string checkDirectory = appSettings.RenameSettings.InPlaceWithOriginalName ? Path.Combine(exifDirectory.FilePath.DirectoryFullPath, exifDirectory.FilePath.FileNameFirstSegment) : exifDirectory.FilePath.DirectoryFullPath; string checkDirectory = appSettings.RenameSettings.InPlaceWithOriginalName ? Path.Combine(exifDirectory.FilePath.DirectoryFullPath, exifDirectory.FilePath.FileNameFirstSegment) : exifDirectory.FilePath.DirectoryFullPath;
string checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}"); string checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile != exifDirectory.FilePath.FullName) if (checkFile != exifDirectory.FilePath.FullName)
@ -421,7 +459,7 @@ public partial class Rename : IRename, IDisposable
dateTime = IDate.GetDateTimeOriginal(firstPass.ExifDirectory); dateTime = IDate.GetDateTimeOriginal(firstPass.ExifDirectory);
hasDateTimeOriginal = dateTime is not null; hasDateTimeOriginal = dateTime is not null;
dateTime ??= IDate.GetMinimum(firstPass.ExifDirectory); dateTime ??= IDate.GetMinimum(firstPass.ExifDirectory);
keywords = IMetadata.GetKeywords(firstPass.ExifDirectory); keywords = IMetaBase.GetKeywords(firstPass.ExifDirectory);
hasIgnoreKeyword = appSettings.MetadataSettings.IgnoreRulesKeyWords.Any(l => keywords.Contains(l)); hasIgnoreKeyword = appSettings.MetadataSettings.IgnoreRulesKeyWords.Any(l => keywords.Contains(l));
record = new(DateTime: dateTime.Value, record = new(DateTime: dateTime.Value,
ExifDirectory: firstPass.ExifDirectory, ExifDirectory: firstPass.ExifDirectory,
@ -435,7 +473,7 @@ public partial class Rename : IRename, IDisposable
return results.AsReadOnly(); return results.AsReadOnly();
} }
private static void SaveIdentifiersToDisk(long ticks, AppSettings appSettings, ReadOnlyCollection<Record> recordCollection) private static void SaveIdentifiersToDisk(AppSettings appSettings, IRename rename, ReadOnlyCollection<Record> recordCollection)
{ {
string paddedId; string paddedId;
Identifier identifier; Identifier identifier;
@ -445,12 +483,12 @@ public partial class Rename : IRename, IDisposable
{ {
if (record.ExifDirectory.FilePath.Id is null) if (record.ExifDirectory.FilePath.Id is null)
continue; continue;
paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, index: null); paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath, record.HasIgnoreKeyword, record.HasDateTimeOriginal, index: null);
identifier = new([], record.HasDateTimeOriginal, record.ExifDirectory.FilePath.Id.Value, record.ExifDirectory.FilePath.Length, paddedId, record.DateTime.Ticks); identifier = new([], record.HasDateTimeOriginal, record.ExifDirectory.FilePath.Id.Value, record.ExifDirectory.FilePath.Length, paddedId, record.DateTime.Ticks);
identifiers.Add(identifier); identifiers.Add(identifier);
} }
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray); string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
_ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); _ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{rename.Ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
} }
private static ReadOnlyCollection<ToDo> GetToDoCollection(AppSettings appSettings, DirectoryInfo directoryInfo, ReadOnlyCollection<int> ids, ReadOnlyCollection<string> files, ReadOnlyCollection<Record> recordCollection) private static ReadOnlyCollection<ToDo> GetToDoCollection(AppSettings appSettings, DirectoryInfo directoryInfo, ReadOnlyCollection<int> ids, ReadOnlyCollection<string> files, ReadOnlyCollection<Record> recordCollection)
@ -462,15 +500,19 @@ public partial class Rename : IRename, IDisposable
string paddedId; string paddedId;
string checkFile; string checkFile;
FilePath filePath; FilePath filePath;
DateTime? dateTime;
FileInfo[] matches; FileInfo[] matches;
FileHolder fileHolder; FileHolder fileHolder;
bool? hasIgnoreKeyword;
string? checkDirectory; string? checkDirectory;
CombinedEnumAndIndex cei; CombinedEnumAndIndex cei;
bool? hasDateTimeOriginal;
const string jpg = ".jpg"; const string jpg = ".jpg";
string checkFileExtension; string checkFileExtension;
List<string> distinct = []; List<string> distinct = [];
const string jpeg = ".jpeg"; const string jpeg = ".jpeg";
string jsonFileSubDirectory; string jsonFileSubDirectory;
ReadOnlyCollection<string> keywords;
bool? directoryCheck = GetDirectoryCheck(appSettings.ResultSettings); bool? directoryCheck = GetDirectoryCheck(appSettings.ResultSettings);
VerifyIntMinValueLength(appSettings.MetadataSettings, recordCollection); VerifyIntMinValueLength(appSettings.MetadataSettings, recordCollection);
bool multipleDirectoriesWithFiles = directoryCheck is not null && directoryCheck.Value; bool multipleDirectoriesWithFiles = directoryCheck is not null && directoryCheck.Value;
@ -481,7 +523,7 @@ public partial class Rename : IRename, IDisposable
record = sorted[i]; record = sorted[i];
if (record.ExifDirectory.FilePath.Id is null) if (record.ExifDirectory.FilePath.Id is null)
continue; continue;
paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, i); paddedId = IId.GetPaddedId(appSettings.ResultSettings, appSettings.MetadataSettings, record.ExifDirectory.FilePath, record.HasIgnoreKeyword, record.HasDateTimeOriginal, i);
checkDirectory = GetCheckDirectory(appSettings, directoryInfo, record, ids, multipleDirectoriesWithFiles, paddedId); checkDirectory = GetCheckDirectory(appSettings, directoryInfo, record, ids, multipleDirectoriesWithFiles, paddedId);
if (string.IsNullOrEmpty(checkDirectory)) if (string.IsNullOrEmpty(checkDirectory))
continue; continue;
@ -496,6 +538,20 @@ public partial class Rename : IRename, IDisposable
if (File.Exists(checkFile)) if (File.Exists(checkFile))
continue; continue;
} }
if (record.ExifDirectory.FilePath.HasDateTimeOriginal is not null && record.ExifDirectory.FilePath.HasIgnoreKeyword is not null)
{
hasIgnoreKeyword = record.ExifDirectory.FilePath.HasIgnoreKeyword;
hasDateTimeOriginal = record.ExifDirectory.FilePath.HasDateTimeOriginal;
}
else
{
dateTime = IDate.GetDateTimeOriginal(record.ExifDirectory);
hasDateTimeOriginal = dateTime is not null;
if (dateTime is null && appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(record.ExifDirectory.FilePath.ExtensionLowered))
continue;
keywords = IMetaBase.GetKeywords(record.ExifDirectory);
hasIgnoreKeyword = appSettings.MetadataSettings.IgnoreRulesKeyWords.Any(keywords.Contains);
}
cei = IPath.GetCombinedEnumAndIndex(appSettings.ResultSettings, record.ExifDirectory.FilePath); cei = IPath.GetCombinedEnumAndIndex(appSettings.ResultSettings, record.ExifDirectory.FilePath);
jsonFile = Path.Combine(jsonFileSubDirectory, cei.Combined, $"{record.ExifDirectory.FilePath.Id.Value}{checkFileExtension}.json"); jsonFile = Path.Combine(jsonFileSubDirectory, cei.Combined, $"{record.ExifDirectory.FilePath.Id.Value}{checkFileExtension}.json");
if (record.JsonFile != jsonFile) if (record.JsonFile != jsonFile)
@ -589,7 +645,7 @@ public partial class Rename : IRename, IDisposable
isWrongYear = null; isWrongYear = null;
string directoryName; string directoryName;
string tfw = GetTFW(record, isWrongYear); string tfw = GetTFW(record, isWrongYear);
string? maker = IMetadata.GetMaker(record.ExifDirectory); string? maker = IMetaBase.GetMaker(record.ExifDirectory);
string rootDirectory = appSettings.ResultSettings.RootDirectory; string rootDirectory = appSettings.ResultSettings.RootDirectory;
string[] segments = checkDirectoryName.Split(years, StringSplitOptions.None); string[] segments = checkDirectoryName.Split(years, StringSplitOptions.None);
(int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear); (int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear);
@ -658,7 +714,7 @@ public partial class Rename : IRename, IDisposable
foreach (ToDo toDo in toDoCollection) foreach (ToDo toDo in toDoCollection)
{ {
if (useProgressBar) if (useProgressBar)
_ProgressBar?.Tick(); rename?.Tick();
if (!toDo.FileInfo.Exists) if (!toDo.FileInfo.Exists)
continue; continue;
if (toDo.JsonFile) if (toDo.JsonFile)
@ -683,8 +739,6 @@ public partial class Rename : IRename, IDisposable
results.Add($"{toDo.FileInfo.FullName}\t{toDo.File}"); results.Add($"{toDo.FileInfo.FullName}\t{toDo.File}");
} }
} }
if (useProgressBar)
_ProgressBar?.Dispose();
return results.AsReadOnly(); return results.AsReadOnly();
} }

View File

@ -9,8 +9,8 @@
<HoursSinceNovember142023>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</HoursSinceNovember142023> <HoursSinceNovember142023>$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</HoursSinceNovember142023>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PackageId>Phares.AA.Shared</PackageId> <PackageId>Phares.Shared</PackageId>
<Version>8.0.114.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</Version> <Version>8.0.118.$([System.Math]::Floor($([MSBuild]::Divide($([MSBuild]::Subtract($([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()), 1699920000)), 3600))))</Version>
<Company>Phares</Company> <Company>Phares</Company>
<Authors>Mike Phares</Authors> <Authors>Mike Phares</Authors>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record AviDirectory(DateTime? DateTimeOriginal, public record AviDirectory(DateTime? DateTimeOriginal,
string? Duration, string? Duration,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record CombinedEnumAndIndex(string Combined, public record CombinedEnumAndIndex(string Combined,
byte Enum, byte Enum,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record DeterministicHashCode(int? Height, public record DeterministicHashCode(int? Height,
int? Id, int? Id,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record DistanceSettings(bool DistanceMoveUnableToMatch, public record DistanceSettings(bool DistanceMoveUnableToMatch,
int FaceAreaPermyriad, int FaceAreaPermyriad,

View File

@ -1,10 +1,9 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record ExifDirectory(AviDirectory[] AviDirectories, public record ExifDirectory(AviDirectory[] AviDirectories,
object? Encoding,
ExifDirectoryBase[] ExifBaseDirectories, ExifDirectoryBase[] ExifBaseDirectories,
FileMetadataDirectory[] FileMetadataDirectories, FileMetadataDirectory[] FileMetadataDirectories,
FilePath FilePath, FilePath FilePath,
@ -28,25 +27,6 @@ public record ExifDirectory(AviDirectory[] AviDirectories,
return result; return result;
} }
public static ExifDirectory Get(object encoding, ExifDirectory e) =>
new(e.AviDirectories,
encoding,
e.ExifBaseDirectories,
e.FileMetadataDirectories,
e.FilePath,
e.GifHeaderDirectories,
e.GpsDirectories,
e.Height,
e.JpegDirectories,
e.MakernoteDirectories,
e.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
e.PhotoshopDirectories,
e.PngDirectories,
e.QuickTimeMovieHeaderDirectories,
e.QuickTimeTrackHeaderDirectories,
e.WebPDirectories,
e.Width);
} }
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] [JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record ExifDirectoryBase(string? Aperture, public record ExifDirectoryBase(string? Aperture,
string? ApplicationNotes, string? ApplicationNotes,
@ -21,9 +21,11 @@ public record ExifDirectoryBase(string? Aperture,
string? FileSource, string? FileSource,
string? ImageDescription, string? ImageDescription,
string? ImageHeight, string? ImageHeight,
int? ImageHeightValue,
string? ImageNumber, string? ImageNumber,
string? ImageUniqueId, string? ImageUniqueId,
string? ImageWidth, string? ImageWidth,
int? ImageWidthValue,
string? IsoSpeed, string? IsoSpeed,
string? LensMake, string? LensMake,
string? LensModel, string? LensModel,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record class FaceDistance : Properties.IFaceDistance public record class FaceDistance : Properties.IFaceDistance
{ {

View File

@ -1,6 +1,6 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FaceEncoding(double[] RawEncoding, int Size); public record FaceEncoding(double[] RawEncoding, int Size);

View File

@ -1,6 +1,6 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FaceFile(int? AreaPermyriad, public record FaceFile(int? AreaPermyriad,
int? ConfidencePercent, int? ConfidencePercent,

View File

@ -1,8 +1,8 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FacePartAndFacePointArray(FacePart FacePart, FacePoint[] FacePoints) public record FacePartAndFacePointArray(FacePart FacePart, FacePoint[] FacePoints)
{ {

View File

@ -1,7 +1,7 @@
using System.Drawing; using System.Drawing;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
[method: JsonConstructor] [method: JsonConstructor]
public class FacePoint(int index, int x, int y) : Properties.IFacePoint public class FacePoint(int index, int x, int y) : Properties.IFacePoint

View File

@ -2,7 +2,7 @@ using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FaceRecognitionGroup(Location Location, ReadOnlyCollection<FaceEncoding?> FaceEncodings, ReadOnlyCollection<ReadOnlyCollection<FacePartAndFacePointArray>> FaceParts) public record FaceRecognitionGroup(Location Location, ReadOnlyCollection<FaceEncoding?> FaceEncodings, ReadOnlyCollection<ReadOnlyCollection<FacePartAndFacePointArray>> FaceParts)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FileHolder(DateTime? CreationTime, public record FileHolder(DateTime? CreationTime,
string? DirectoryFullPath, string? DirectoryFullPath,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FileMetadataDirectory(DateTime? FileModifiedDate, public record FileMetadataDirectory(DateTime? FileModifiedDate,
string? FileName, string? FileName,

View File

@ -1,8 +1,8 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FilePath(long CreationTicks, public record FilePath(long CreationTicks,
string DirectoryFullPath, string DirectoryFullPath,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FilePathAndWholePercentages(FilePath FilePath, int WholePercentages) public record FilePathAndWholePercentages(FilePath FilePath, int WholePercentages)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record FirstPass(ExifDirectory ExifDirectory, public record FirstPass(ExifDirectory ExifDirectory,
bool FastForwardMovingPictureExpertsGroupUsed, bool FastForwardMovingPictureExpertsGroupUsed,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record GifHeaderDirectory(string? ImageHeight, public record GifHeaderDirectory(string? ImageHeight,
string? ImageWidth) string? ImageWidth)

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record GpsDirectory(string? Altitude, public record GpsDirectory(string? Altitude,
string? Latitude, string? Latitude,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record JpegDirectory(string? ImageHeight, public record JpegDirectory(string? ImageHeight,
string? ImageWidth) string? ImageWidth)

View File

@ -1,6 +1,6 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
[method: JsonConstructor] [method: JsonConstructor]
public class Location(int bottom, double confidence, int left, int right, int top) : Properties.ILocation, IEquatable<Location> public class Location(int bottom, double confidence, int left, int right, int top) : Properties.ILocation, IEquatable<Location>

View File

@ -1,6 +1,7 @@
using System.Drawing; using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record LocationContainer(DateOnly? CreationDateOnly, public record LocationContainer(DateOnly? CreationDateOnly,
ExifDirectory? ExifDirectory, ExifDirectory? ExifDirectory,
@ -10,40 +11,67 @@ public record LocationContainer(DateOnly? CreationDateOnly,
int? LengthPermyriad, int? LengthPermyriad,
FilePath? LengthSource, FilePath? LengthSource,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
RectangleF? Rectangle,
int? WholePercentages) int? WholePercentages)
{ {
public static LocationContainer Get(LocationContainer locationContainer, object? encoding, bool keepExifDirectory) public string GetWithoutEncoding()
{
string result;
WithoutEncoding withoutEncoding = new(CreationDateOnly: CreationDateOnly,
ExifDirectory: ExifDirectory,
FaceFile: FaceFile,
FilePath: FilePath,
LengthPermyriad: LengthPermyriad,
LengthSource: LengthSource,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
WholePercentages: WholePercentages);
result = JsonSerializer.Serialize(withoutEncoding, WithoutEncodingSourceGenerationContext.Default.WithoutEncoding);
return result;
}
public static LocationContainer Get(LocationContainer locationContainer, object? encoding)
{ {
LocationContainer result; LocationContainer result;
result = new(locationContainer.CreationDateOnly, result = new(CreationDateOnly: locationContainer.CreationDateOnly,
keepExifDirectory ? locationContainer.ExifDirectory : null, ExifDirectory: locationContainer.ExifDirectory,
encoding, Encoding: encoding,
locationContainer.FaceFile, FaceFile: locationContainer.FaceFile,
locationContainer.FilePath, FilePath: locationContainer.FilePath,
locationContainer.LengthPermyriad, LengthPermyriad: locationContainer.LengthPermyriad,
locationContainer.LengthSource, LengthSource: locationContainer.LengthSource,
locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
locationContainer.Rectangle, WholePercentages: locationContainer.WholePercentages);
locationContainer.WholePercentages);
return result; return result;
} }
public static LocationContainer Get(LocationContainer source, LocationContainer locationContainer, int lengthPermyriad, bool keepExifDirectory, bool keepEncoding) public static LocationContainer Get(LocationContainer source, LocationContainer locationContainer, int lengthPermyriad, bool keepExifDirectory, bool keepEncoding)
{ {
LocationContainer result; LocationContainer result;
result = new(locationContainer.CreationDateOnly, result = new(CreationDateOnly: locationContainer.CreationDateOnly,
keepExifDirectory ? locationContainer.ExifDirectory : null, ExifDirectory: keepExifDirectory ? locationContainer.ExifDirectory : null,
keepEncoding ? locationContainer.Encoding : null, Encoding: keepEncoding ? locationContainer.Encoding : null,
locationContainer.FaceFile, FaceFile: locationContainer.FaceFile,
locationContainer.FilePath, FilePath: locationContainer.FilePath,
lengthPermyriad, LengthPermyriad: lengthPermyriad,
source.FilePath, LengthSource: source.FilePath,
locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
locationContainer.Rectangle, WholePercentages: locationContainer.WholePercentages);
locationContainer.WholePercentages);
return result; return result;
} }
}
internal record WithoutEncoding(DateOnly? CreationDateOnly,
ExifDirectory? ExifDirectory,
FaceFile? FaceFile,
FilePath FilePath,
int? LengthPermyriad,
FilePath? LengthSource,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName? PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
int? WholePercentages);
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(WithoutEncoding))]
internal partial class WithoutEncodingSourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MakernoteDirectory(string? CameraSerialNumber, public record MakernoteDirectory(string? CameraSerialNumber,
string? FirmwareVersion, string? FirmwareVersion,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MappingFromFilter(bool? IsFocusModel, public record MappingFromFilter(bool? IsFocusModel,
bool? IsFocusPerson, bool? IsFocusPerson,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MappingFromFilterPost(bool? CanReMap, public record MappingFromFilterPost(bool? CanReMap,
bool? InSkipCollection, bool? InSkipCollection,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MappingFromPerson(int? ApproximateYears, public record MappingFromPerson(int? ApproximateYears,
string DisplayDirectoryName, string DisplayDirectoryName,

135
Shared/Models/MetaBase.cs Normal file
View File

@ -0,0 +1,135 @@
using System.Collections.ObjectModel;
using System.Globalization;
namespace Phares.Shared.Models;
internal static class MetaBase
{
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;
}
}
}
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;
}
}
}
return result;
}
internal static int? GetOrientation(ExifDirectoryBase[]? exifBaseDirectories)
{
int? result = null;
// public const int TagOrientation = 274;
if (exifBaseDirectories is not null)
{
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
result = exifDirectoryBase?.OrientationValue;
if (result is not null)
break;
}
}
return result;
}
internal static ReadOnlyCollection<string> GetKeywords(ExifDirectoryBase[]? exifBaseDirectories)
{
List<string> results = [];
if (exifBaseDirectories is not null)
{
string value;
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
value = exifDirectoryBase?.WinKeywords is null ? string.Empty : exifDirectoryBase.WinKeywords.ToString().Trim();
if (string.IsNullOrEmpty(value))
continue;
results.Add(value);
}
}
return results.AsReadOnly();
}
internal static int? GetWidth(ExifDirectoryBase[]? exifBaseDirectories)
{
int? result = null;
// public const int TagImageWidth = 256;
if (exifBaseDirectories is not null)
{
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
result = exifDirectoryBase?.ImageWidthValue;
if (result is not null)
break;
}
}
return result;
}
internal static int? GetHeight(ExifDirectoryBase[]? exifBaseDirectories)
{
int? result = null;
// public const int TagImageHeight = 257;
if (exifBaseDirectories is not null)
{
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
result = exifDirectoryBase?.ImageHeightValue;
if (result is not null)
break;
}
}
return result;
}
#pragma warning disable CA1416
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
{
DateTime? result;
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;
}
#pragma warning restore CA1416
}

View File

@ -2,7 +2,7 @@ using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MetadataGroup(bool FastForwardMovingPictureExpertsGroupUsed, FilePath FilePath, MinimumYearAndPathCombined MinimumYearAndPathCombined, ExifDirectory ExifDirectory, ReadOnlyCollection<FileHolder> SidecarFiles) public record MetadataGroup(bool FastForwardMovingPictureExpertsGroupUsed, FilePath FilePath, MinimumYearAndPathCombined MinimumYearAndPathCombined, ExifDirectory ExifDirectory, ReadOnlyCollection<FileHolder> SidecarFiles)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MetadataSettings(bool ForceMetadataLastWriteTimeToCreationTime, public record MetadataSettings(bool ForceMetadataLastWriteTimeToCreationTime,
string[] IgnoreRulesKeyWords, string[] IgnoreRulesKeyWords,
@ -20,6 +20,6 @@ public record MetadataSettings(bool ForceMetadataLastWriteTimeToCreationTime,
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(MetadataSettings))] [JsonSerializable(typeof(MetadataSettings))]
internal partial class MetadataSettingsSourceGenerationContext : JsonSerializerContext public partial class MetadataSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record MinimumYearAndPathCombined(int MinimumYear, public record MinimumYearAndPathCombined(int MinimumYear,
string PathCombined) string PathCombined)

View File

@ -2,7 +2,7 @@ using System.Globalization;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record NginxFileSystem([property: JsonPropertyName("name")] string Name, public record NginxFileSystem([property: JsonPropertyName("name")] string Name,
DateTime? LastModified, DateTime? LastModified,

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record OutputResolution(int Height, public record OutputResolution(int Height,
int Orientation, int Orientation,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PeopleSettings(string GenealogicalDataCommunicationFile, public record PeopleSettings(string GenealogicalDataCommunicationFile,
string[] JLinks, string[] JLinks,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PersonBirthday(DateTime Value) public record PersonBirthday(DateTime Value)
{ {

View File

@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Stateless; using Phares.Shared.Models.Stateless;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PersonContainer(int? ApproximateYears, public record PersonContainer(int? ApproximateYears,
PersonBirthday[]? Birthdays, PersonBirthday[]? Birthdays,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PersonDirectory(char Char, string Group, char Status, char Sex, char First) public record PersonDirectory(char Char, string Group, char Status, char Sex, char First)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PersonKeyFormattedAndPersonBirthday(string PersonKeyFormatted, PersonBirthday PersonBirthday) public record PersonKeyFormattedAndPersonBirthday(string PersonKeyFormatted, PersonBirthday PersonBirthday)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName(string KeyFormatted, public record PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName(string KeyFormatted,
long KeyTicks, long KeyTicks,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PhotoshopDirectory(string? JpegQuality, public record PhotoshopDirectory(string? JpegQuality,
string? Url) string? Url)

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record PngDirectory(string? ImageHeight, public record PngDirectory(string? ImageHeight,
string? ImageWidth, string? ImageWidth,

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface ICompareSettings public interface ICompareSettings
{ {

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface IFaceDistance public interface IFaceDistance
{ {

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface IFacePoint public interface IFacePoint
{ {

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface ILocation public interface ILocation
{ {

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface IRenameSettings public interface IRenameSettings
{ {

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models.Properties; namespace Phares.Shared.Models.Properties;
public interface IWindowsSettings public interface IWindowsSettings
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record QuickTimeMovieHeaderDirectory(DateTime? Created) public record QuickTimeMovieHeaderDirectory(DateTime? Created)
{ {

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record QuickTimeTrackHeaderDirectory(DateTime? Created) public record QuickTimeTrackHeaderDirectory(DateTime? Created)
{ {

View File

@ -2,7 +2,7 @@ using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record ReadOnlyCollections(ReadOnlyCollection<long> JLinkResolvedPersonKeys, public record ReadOnlyCollections(ReadOnlyCollection<long> JLinkResolvedPersonKeys,
ReadOnlyCollection<PersonContainer> PersonContainers, ReadOnlyCollection<PersonContainer> PersonContainers,

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record ResultSettings(string DateGroup, public record ResultSettings(string DateGroup,
int EpicYear, int EpicYear,
@ -29,6 +29,6 @@ public record ResultSettings(string DateGroup,
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ResultSettings))] [JsonSerializable(typeof(ResultSettings))]
internal partial class ResultSettingsSourceGenerationContext : JsonSerializerContext public partial class ResultSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

@ -1,7 +1,7 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace Phares.Shared.Models;
public record SaveContainer(string CheckFile, public record SaveContainer(string CheckFile,
string Directory, string Directory,

Some files were not shown because too many files have changed in this diff Show More