Removed Rectangle from LocationContainer

mapped-ids-then-whole-percentages-to-location-container

save-extracted-face

save-extracted-java-script-object-notation
This commit is contained in:
2025-07-06 10:45:59 -07:00
parent 2c9b1a68c0
commit 05fb8685d9
13 changed files with 327 additions and 208 deletions

View File

@ -1,6 +1,7 @@
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;
@ -62,22 +63,25 @@ public partial class Compare : ICompare, IDisposable
ReadOnlyDictionary<string, LocationContainer> onlyOne; ReadOnlyDictionary<string, LocationContainer> onlyOne;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, compare); bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, compare);
ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings); ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings);
ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding = GetMappedExifDirectoryWithEncoding(appSettings, compare, 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;
logger?.LogInformation("{outputResolution}", outputResolution); logger?.LogInformation("{outputResolution}", outputResolution);
exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, outputResolution); exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, outputResolution);
preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, 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, 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);
@ -155,16 +159,127 @@ public partial class Compare : ICompare, IDisposable
return result; return result;
} }
private static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(AppSettings appSettings, ICompare compare, 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, 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, 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

@ -9,7 +9,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) : Shared.Models.Properties.ICompareSettings
{ {
public override string ToString() public override string ToString()

View File

@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Distance.Models.Stateless; namespace View_by_Distance.Distance.Models.Stateless;
@ -8,27 +9,135 @@ namespace View_by_Distance.Distance.Models.Stateless;
internal static class FaceEncodingLogic internal static class FaceEncodingLogic
{ {
internal static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(ICompare compare, 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;
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); 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;
string? json;
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));
json = Metadata.Models.Stateless.IMetadata.GetFaceEncoding(exifDirectory);
faceEncoding = json is null ? null : JsonSerializer.Deserialize(json, FaceEncodingGenerationContext.Default.FaceEncoding);
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;
string? json = Metadata.Models.Stateless.IMetadata.GetOutputResolution(exifDirectory);
if (json is null || !json.Contains(nameof(DateTime)))
{
if (distanceSettings.DistanceMoveUnableToMatch)
MoveUnableToMatch(exifDirectory.FilePath);
result = null;
}
else
{
result = JsonSerializer.Deserialize(json, FaceFileGenerationContext.Default.FaceFile);
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

@ -32,7 +32,7 @@ internal static class FilterLogicA
return result; return result;
} }
internal static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, 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? json;
@ -41,8 +41,8 @@ internal static class FilterLogicA
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, exifDirectories, nameof(FilterLogicA)); ReadOnlyCollection<LocationContainer> locationContainers = FilterLogicB.GetLocationContainers(distanceSettings, compareSettings, compare, exifDirectories, nameof(FilterLogicA));
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.Ticks).TotalSeconds);
@ -53,7 +53,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;
@ -85,7 +85,7 @@ internal static class FilterLogicA
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,6 +1,4 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Drawing;
using System.Text.Json;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -10,71 +8,30 @@ namespace View_by_Distance.Distance.Models.Stateless;
internal static class FilterLogicB internal static class FilterLogicB
{ {
private static void MoveUnableToMatch(FilePath filePath)
{
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(CreationDateOnly: dateOnly,
ExifDirectory: exifDirectory,
Encoding: exifDirectory.Encoding,
FaceFile: faceFile,
FilePath: exifDirectory.FilePath,
LengthPermyriad: null,
LengthSource: null,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: exifDirectory.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
Rectangle: rectangle,
WholePercentages: wholePercentages);
lock (locationContainers)
locationContainers.Add(locationContainer);
}
internal static ReadOnlyCollection<LocationContainer> GetLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> exifDirectories, string sourceClass) internal static ReadOnlyCollection<LocationContainer> GetLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, 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 - compare.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

@ -24,22 +24,24 @@ internal static class FilterLogicC
return results.AsReadOnly(); return results.AsReadOnly();
} }
private static ReadOnlyCollection<LocationContainer> GetCombined(DistanceSettings distanceSettings, Shared.Models.Properties.ICompareSettings compareSettings, ICompare compare, 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, 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, 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, mappedExifDirectoryWithEncoding, postFiltered); ReadOnlyCollection<LocationContainer> locationContainers = GetCombined(mappedIdsThenWholePercentagesToLocationContainer, postFiltered);
string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - compare.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

@ -9,7 +9,7 @@ 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, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
FaceEncodingLogic.GetMappedExifDirectoryWithEncoding(compare, 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) =>
MappedLogicA.Extract(compareSettings, exifDirectories);
public static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) => public static void SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
FilterLogicD.SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers); FilterLogicD.SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers);
public static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) => public static ReadOnlyCollection<SaveContainer> GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne); FilterLogicD.GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne);
public static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) => public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompare compare, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
MappedLogicA.GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections); FilterLogicC.GetMatrixLocationContainers(distanceSettings, compare, mappedIdsThenWholePercentagesToLocationContainer, distanceLimits, postFiltered);
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) => public static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> GetMappedIdsThenWholePercentagesToLocationContainer(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) =>
FilterLogicC.GetMatrixLocationContainers(distanceSettings, compareSettings, compare, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered); FaceEncodingLogic.GetMappedIdsThenWholePercentagesToLocationContainer(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections);
public static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) => public static ReadOnlyCollection<LocationContainer> GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, keyValuePairs, exifDirectories); FilterLogicA.GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, mappedIdsThenWholePercentagesToLocationContainer, 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, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
GetMappedExifDirectoryWithEncoding(compare, 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) =>
Extract(compareSettings, exifDirectories);
internal static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) => internal static void TestStatic_SaveContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, int? updated, ReadOnlyCollection<SaveContainer> saveContainers) =>
SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers); SaveContainers(distanceSettings, compareSettings, compare, updated, saveContainers);
internal static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) => internal static ReadOnlyCollection<SaveContainer> TestStatic_GetSaveContainers(ResultSettings resultSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, string outputResolution, ReadOnlyDictionary<string, LocationContainer> onlyOne) =>
GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne); GetSaveContainers(resultSettings, distanceSettings, compareSettings, compare, outputResolution, onlyOne);
internal static ReadOnlyCollection<ExifDirectory> TestStatic_GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) => internal static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompare compare, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) =>
GetMapped(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections); GetMatrixLocationContainers(distanceSettings, compare, mappedIdsThenWholePercentagesToLocationContainer, distanceLimits, postFiltered);
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetMatrixLocationContainers(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding, DistanceLimits distanceLimits, ReadOnlyCollection<LocationContainer> postFiltered) => internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> TestStatic_GetMappedIdsThenWholePercentagesToLocationContainer(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections) =>
GetMatrixLocationContainers(distanceSettings, compareSettings, compare, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered); GetMappedIdsThenWholePercentagesToLocationContainer(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings, compare, readOnlyCollections);
internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs, ReadOnlyCollection<ExifDirectory> exifDirectories) => internal static ReadOnlyCollection<LocationContainer> TestStatic_GetPreFilterLocationContainer(DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedIdsThenWholePercentagesToLocationContainer, ReadOnlyCollection<ExifDirectory> exifDirectories) =>
GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, keyValuePairs, exifDirectories); GetPreFilterLocationContainer(distanceSettings, compareSettings, compare, readOnlyCollections, mappedIdsThenWholePercentagesToLocationContainer, exifDirectories);
} }

View File

@ -14,32 +14,6 @@ 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)
{
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, ReadOnlyCollections readOnlyCollections) internal static ReadOnlyCollection<ExifDirectory> GetMapped(ResultSettings resultSettings, MetadataSettings metadataSettings, PeopleSettings peopleSettings, DistanceSettings distanceSettings, ICompareSettings compareSettings, ICompare compare, ReadOnlyCollections readOnlyCollections)
{ {
List<ExifDirectory> results = []; List<ExifDirectory> results = [];

View File

@ -529,7 +529,6 @@ internal abstract class Exif
Shared.Models.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories); Shared.Models.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories);
Shared.Models.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories); Shared.Models.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories);
result = new(aviDirectories, result = new(aviDirectories,
null,
exifBaseDirectories, exifBaseDirectories,
fileMetadataDirectories, fileMetadataDirectories,
filePath, filePath,

View File

@ -4,7 +4,6 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.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,4 +1,5 @@
using System.Drawing; using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models; namespace View_by_Distance.Shared.Models;
@ -10,22 +11,35 @@ 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(CreationDateOnly: locationContainer.CreationDateOnly, result = new(CreationDateOnly: locationContainer.CreationDateOnly,
ExifDirectory: keepExifDirectory ? locationContainer.ExifDirectory : null, ExifDirectory: locationContainer.ExifDirectory,
Encoding: encoding, Encoding: encoding,
FaceFile: locationContainer.FaceFile, FaceFile: locationContainer.FaceFile,
FilePath: locationContainer.FilePath, FilePath: locationContainer.FilePath,
LengthPermyriad: locationContainer.LengthPermyriad, LengthPermyriad: locationContainer.LengthPermyriad,
LengthSource: locationContainer.LengthSource, LengthSource: locationContainer.LengthSource,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
Rectangle: locationContainer.Rectangle,
WholePercentages: locationContainer.WholePercentages); WholePercentages: locationContainer.WholePercentages);
return result; return result;
} }
@ -41,9 +55,23 @@ public record LocationContainer(DateOnly? CreationDateOnly,
LengthPermyriad: lengthPermyriad, LengthPermyriad: lengthPermyriad,
LengthSource: source.FilePath, LengthSource: source.FilePath,
PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName, PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName: locationContainer.PersonKeyFormattedAndKeyTicksAndDisplayDirectoryName,
Rectangle: locationContainer.Rectangle,
WholePercentages: locationContainer.WholePercentages); 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

@ -5,11 +5,6 @@ namespace View_by_Distance.Shared.Models.Stateless;
public interface ILocation public interface ILocation
{ {
RectangleF? TestStatic_GetPercentagesRectangle(DistanceSettings distanceSettings, int wholePercentages) =>
GetPercentagesRectangle(distanceSettings, wholePercentages);
static RectangleF? GetPercentagesRectangle(DistanceSettings distanceSettings, int wholePercentages) =>
Location.GetPercentagesRectangle(distanceSettings, wholePercentages);
Models.Location TestStatic_GetTrimBound(double detectionConfidence, Rectangle rectangle, int width, int height, int facesCount) => Models.Location TestStatic_GetTrimBound(double detectionConfidence, Rectangle rectangle, int width, int height, int facesCount) =>
TrimBound(detectionConfidence, rectangle, width, height, facesCount); TrimBound(detectionConfidence, rectangle, width, height, facesCount);
static Models.Location TrimBound(double detectionConfidence, Rectangle rectangle, int width, int height, int facesCount) => static Models.Location TrimBound(double detectionConfidence, Rectangle rectangle, int width, int height, int facesCount) =>

View File

@ -1,6 +1,4 @@
using System.Drawing; namespace View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Shared.Models.Stateless;
internal abstract class Location internal abstract class Location
{ {
@ -47,32 +45,4 @@ internal abstract class Location
return result; return result;
} }
internal static RectangleF? GetPercentagesRectangle(DistanceSettings distanceSettings, int wholePercentages)
{
RectangleF? result;
string wp = wholePercentages.ToString();
int length = (distanceSettings.LocationDigits - 1) / 4;
string[] segments =
[
wp[..1],
wp.Substring(1, length),
wp.Substring(3, length),
wp.Substring(5, length),
wp.Substring(7, length)
];
if (string.Join(string.Empty, segments) != wp)
result = null;
else
{
if (!int.TryParse(segments[1], out int xWholePercent) || !int.TryParse(segments[2], out int yWholePercent) || !int.TryParse(segments[3], out int wWholePercent) || !int.TryParse(segments[4], out int hWholePercent))
result = null;
else
{
float factor = 100;
result = new(xWholePercent / factor, yWholePercent / factor, wWholePercent / factor, hWholePercent / factor);
}
}
return result;
}
} }