From 45f4401fa42aaaa36665d9e00ea3b4bb3ad5000d Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sat, 31 Dec 2022 13:10:03 -0700 Subject: [PATCH] _Original --- Drag-Drop/Form.cs | 11 +- Face/Models/_D_Face.cs | 28 +++-- Instance/DlibDotNet.cs | 113 +++++++++++------ Instance/Models/Binder/Configuration.cs | 4 + Instance/Models/Configuration.cs | 3 + Instance/appsettings.Development.json | 11 +- Instance/appsettings.json | 2 + Resize/Models/_C_Resize.cs | 116 ++++++++---------- Shared/Models/Methods/IResize.cs | 8 ++ Shared/Models/Stateless/Methods/ILocation.cs | 7 +- Shared/Models/Stateless/Methods/Location.cs | 21 +++- Tests/UnitTestResize.cs | 7 +- .../UnitTestFace.cs | 7 +- 13 files changed, 197 insertions(+), 141 deletions(-) create mode 100644 Shared/Models/Methods/IResize.cs diff --git a/Drag-Drop/Form.cs b/Drag-Drop/Form.cs index daf969d..202f2b3 100644 --- a/Drag-Drop/Form.cs +++ b/Drag-Drop/Form.cs @@ -240,7 +240,16 @@ public partial class Form : System.Windows.Forms.Form { checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}{checkFileExtension}"); - if (checkFile == fileHolder.FullName || File.Exists(checkFile)) + if (checkFile == fileHolder.FullName) + continue; + for (int i = 0; i < int.MaxValue; i++) + { + checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks + i}{checkFileExtension}"); + if (File.Exists(checkFile)) + continue; + break; + } + if (File.Exists(checkFile)) continue; File.Move(fileHolder.FullName, checkFile); File.WriteAllText($"{checkFile}.id", $"{id.Value}{Environment.NewLine}{fileHolder.Name}"); diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index a1eb1ad..96d2315 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -218,7 +218,7 @@ public class D_Face } } - private List GetFaces(Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List? locations) + private List GetFaces(Shared.Models.Methods.IResize resize, string outputResolution, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List? locations) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -237,6 +237,7 @@ public class D_Face } if (unknownImage is not null) { + (int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) = resize.Get(outputResolution, outputResolutionToResize); List<(Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary? FaceParts)> collection; FaceRecognition faceRecognition = new(_Configuration.NumberOfJitters.Value, _Configuration.NumberOfTimesToUpsample.Value, _Model, _ModelParameter, _PredictorModel); collection = faceRecognition.GetCollection(unknownImage, locations, includeFaceEncoding: true, includeFaceParts: true); @@ -297,7 +298,7 @@ public class D_Face #pragma warning restore CA1416 - private static List> GetCollection(int outputResolutionWidth, int outputResolutionHeight, List> collection, List faces) + private static List> GetCollection(Shared.Models.Methods.IResize resize, string outputResolution, List> collection, Dictionary outputResolutionToResize, List faces) { List> results = new(); string? json; @@ -305,7 +306,8 @@ public class D_Face Location? location; Rectangle? rectangle; List skip = new(); - OutputResolution? outputResolution = null; + OutputResolution? outputResolutionCheck = null; + (int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation) = resize.Get(outputResolution, outputResolutionToResize); foreach (Shared.Models.Face face in faces) { if (face.Location is null || face.OutputResolution is null) @@ -325,8 +327,8 @@ public class D_Face json = Metadata.Models.Stateless.IMetadata.GetOutputResolution(locationContainer.Directories); if (json is not null) { - outputResolution = JsonSerializer.Deserialize(json); - if (outputResolution is not null && (outputResolution.Width != outputResolutionWidth || outputResolution.Height != outputResolutionHeight)) + outputResolutionCheck = JsonSerializer.Deserialize(json); + if (outputResolutionCheck is not null && (outputResolutionCheck.Width != outputResolutionWidth || outputResolutionCheck.Height != outputResolutionHeight)) continue; } (width, height) = Get(locationContainer.File); @@ -341,11 +343,11 @@ public class D_Face } } if (results.Any()) - outputResolution = null; + outputResolutionCheck = null; return results; } - public List GetFaces(string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, List>? collection, List? mappingFromPhotoPrismCollection) + public List GetFaces(Shared.Models.Methods.IResize resize, string outputResolution, string dResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize, List>? collection, List? mappingFromPhotoPrismCollection) { List? results; if (string.IsNullOrEmpty(dResultsFullGroupDirectory)) @@ -388,18 +390,18 @@ public class D_Face parseExceptions.Add(nameof(D_Face)); } } - List> containers; + List> locationContainers; if (results is null || collection is null) - containers = new(); + locationContainers = new(); else - containers = GetCollection(outputResolutionWidth, outputResolutionHeight, collection, results); + locationContainers = GetCollection(resize, outputResolution, collection, outputResolutionToResize, results); if (mappingFromPhotoPrismCollection is null || results is null) - locations = (from l in containers where l is not null select l.Location).ToList(); + locations = (from l in locationContainers where l is not null select l.Location).ToList(); else - locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results, containers); + locations = Shared.Models.Stateless.Methods.ILocation.GetLocations(mappingFromPhotoPrismCollection, results, locationContainers); if (results is null || (locations is not null && locations.Any())) { - results = GetFaces(property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, locations); + results = GetFaces(resize, outputResolution, property, mappingFromItem, outputResolutionToResize, locations); if (!results.Any()) File.Move(mappingFromItem.ResizedFileHolder.FullName, $"{mappingFromItem.ResizedFileHolder.FullName}.err"); else diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 07ab529..2bdd207 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -2,6 +2,7 @@ using Phares.Shared; using ShellProgressBar; using System.Diagnostics; +using System.Drawing; using System.Drawing.Imaging; using System.Text.Json; using View_by_Distance.Distance.Models; @@ -62,7 +63,7 @@ public partial class DlibDotNet Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _Log.Information(propertyConfiguration.RootDirectory); Property.Models.Configuration.Verify(propertyConfiguration, requireExist: false); - Verify(configuration); + OpenPossibleDuplicates(configuration); VerifyExtra(args, propertyConfiguration, configuration); _Configuration = configuration; _Index = new(configuration); @@ -205,7 +206,7 @@ public partial class DlibDotNet return result; } - private void Verify(Models.Configuration configuration) + private void OpenPossibleDuplicates(Models.Configuration configuration) { if (!configuration.OutputResolutions.Any() || string.IsNullOrEmpty(configuration.OutputResolutions[0]) || !configuration.ValidResolutions.Contains(configuration.OutputResolutions[0])) throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be _FileNameToCollection valid outputResolution!"); @@ -289,13 +290,11 @@ public partial class DlibDotNet { if (_Log is null) throw new NullReferenceException(nameof(_Log)); - string original = "Original"; List faces; Shared.Models.Property property; long ticks = DateTime.Now.Ticks; DateTime dateTime = DateTime.Now; List parseExceptions = new(); - Dictionary imageResizeKeyValuePairs; List> subFileTuples = new(); List> metadataCollection; if (item.Property is not null && item.Property.Id is not null && !item.Any()) @@ -343,33 +342,21 @@ public partial class DlibDotNet (int metadataGroups, metadataCollection) = _Metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); - imageResizeKeyValuePairs = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item.Property, mappingFromItem); + Dictionary outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.GetResizeKeyValuePairs)); if (_Configuration.SaveResizedSubfiles) { - _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, original, imageResizeKeyValuePairs); + _Resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(C_Resize.SaveResizedSubfile)); } - else if (outputResolution == _Configuration.OutputResolutions[0] && false) - { - byte[] bytes = _Resize.GetResizedBytes(outputResolution, cResultsFullGroupDirectory, subFileTuples, item.Property, mappingFromItem, imageResizeKeyValuePairs); - if (_AppSettings.MaxDegreeOfParallelism < 2) - ticks = LogDelta(ticks, nameof(C_Resize.GetResizedBytes)); - string path = Path.Combine(resizedFileHolder.DirectoryName, resizedFileHolder.NameWithoutExtension); - File.WriteAllBytes(path, bytes); - } if (!mappingFromItem.ResizedFileHolder.Exists && !File.Exists(mappingFromItem.ResizedFileHolder.FullName)) faces = new(); else if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) faces = new(); else { - int[] outputResolutionCollection = imageResizeKeyValuePairs[outputResolution]; - int outputResolutionWidth = outputResolutionCollection[0]; - int outputResolutionHeight = outputResolutionCollection[1]; - int outputResolutionOrientation = outputResolutionCollection[2]; List? mappingFromPhotoPrismCollection; List>? collection; if (item.Property?.Id is null) @@ -378,7 +365,7 @@ public partial class DlibDotNet _ = idToMappedFaceFilesWithCollection.TryGetValue(item.Property.Id.Value, out collection); if (!_FileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection)) mappingFromPhotoPrismCollection = null; - faces = _Faces.GetFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation, collection, mappingFromPhotoPrismCollection); + faces = _Faces.GetFaces(_Resize, outputResolution, dResultsFullGroupDirectory, subFileTuples, parseExceptions, property, mappingFromItem, outputResolutionToResize, collection, mappingFromPhotoPrismCollection); if (_AppSettings.MaxDegreeOfParallelism < 2) ticks = LogDelta(ticks, nameof(D_Face.GetFaces)); bool anyFacesSaved = _Faces.SaveFaces(dResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem, facesDirectory, faces); @@ -402,7 +389,7 @@ public partial class DlibDotNet imageFaceCollections[index] = faces; propertyCollection[index] = property; metadataCollections[index] = metadataCollection; - resizeKeyValuePairs[index] = imageResizeKeyValuePairs; + resizeKeyValuePairs[index] = outputResolutionToResize; propertyFileHolderCollection[index] = item.ImageFileHolder; sourceDirectoryChanges.AddRange(from l in subFileTuples where l.Item2 > dateTime select l); } @@ -991,35 +978,81 @@ public partial class DlibDotNet directories = new List(); else directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); + Rectangle? rectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(_Configuration.LocationDigits, normalizedRectangle.Value); lock (collection) - collection.Add(new(fromDistanceContent, file, personKey, id.Value, normalizedRectangle.Value, directories, null, null)); + collection.Add(new(fromDistanceContent, file, personKey, id.Value, normalizedRectangle.Value, directories, rectangle, null)); } - private void Verify(List> collection) + private void OpenPossibleDuplicates(List<(long, int, string, double?)> duplicates) { - string key; - int normalizedRectangle; string personKeyFormatted; - Dictionary distinct = new(); - List<(long, int, string)> duplicates = new(); - foreach (LocationContainer locationContainer in collection) + foreach ((long personKey, int id, string file, double? percent) in duplicates) { - key = string.Concat(locationContainer.PersonKey, locationContainer.Id); - if (distinct.TryGetValue(key, out normalizedRectangle)) - { - if (normalizedRectangle == locationContainer.NormalizedRectangle) - continue; - duplicates.Add(new(locationContainer.PersonKey, locationContainer.Id, locationContainer.File)); + if (percent is null) continue; - } - distinct.Add(key, locationContainer.NormalizedRectangle); - } - (); //Do they also intersect? - foreach ((long personKey, int id, string file) in duplicates) - { _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personKey); } + foreach ((long personKey, int id, string file, double? percent) in duplicates) + { + if (percent is not null && percent.Value == 0) + continue; + _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); + personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personKey); + } + foreach ((long personKey, int id, string file, double? percent) in duplicates) + { + if (percent is not null && percent.Value > 0) + continue; + _ = Process.Start("explorer.exe", string.Concat("\"", Path.GetDirectoryName(file), "\"")); + personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personKey); + } + } + + private void LookForPossibleDuplicates(List> collection) + { + string key; + double? percent; + Rectangle? rectangle; + Rectangle intersectRectangle; + (string File, int NormalizedRectangle) item; + Dictionary distinct = new(); + List<(long, int, string, double?)> duplicates = new(); + foreach (LocationContainer locationContainer in collection) + { + key = string.Concat(locationContainer.PersonKey, locationContainer.Id); + if (distinct.TryGetValue(key, out item)) + { + if (item.NormalizedRectangle == locationContainer.NormalizedRectangle) + continue; + if (locationContainer.Rectangle is null) + percent = null; + else + { + rectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(_Configuration.LocationDigits, item.NormalizedRectangle); + if (locationContainer.Rectangle is null || rectangle is null) + percent = null; + else + { + intersectRectangle = Rectangle.Intersect(locationContainer.Rectangle.Value, rectangle.Value); + percent = intersectRectangle.Width * intersectRectangle.Height; + } + } + if (!_Configuration.DeletePossibleDuplicates) + duplicates.Add(new(locationContainer.PersonKey, locationContainer.Id, locationContainer.File, percent)); + else + { + if (File.Exists(item.File)) + File.Delete(item.File); + if (File.Exists(locationContainer.File)) + File.Delete(locationContainer.File); + } + continue; + } + distinct.Add(key, new(locationContainer.File, locationContainer.NormalizedRectangle)); + } + if (duplicates.Any() && _IsEnvironment.Development) + OpenPossibleDuplicates(duplicates); } private List> GetCollection(long ticks, string? a2PeopleContentDirectory, string eDistanceContentDirectory) @@ -1052,7 +1085,7 @@ public partial class DlibDotNet ParallelFor(eDistanceContentDirectory, results, collection[i].PersonKey, collection[i].File); }); } - Verify(results); + LookForPossibleDuplicates(results); return results; } diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index 8a45029..8232abe 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -13,6 +13,7 @@ public class Configuration [Display(Name = "Check D Face and Up Dates"), Required] public bool? CheckDFaceAndUpWriteDates { get; set; } [Display(Name = "Check Json For Distance Results"), Required] public bool? CheckJsonForDistanceResults { get; set; } [Display(Name = "CrossDirectory Max Items In Distance Collection"), Required] public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; } + [Display(Name = "Delete Possible Duplicates"), Required] public bool? DeletePossibleDuplicates { get; set; } [Display(Name = "Distance Factor"), Required] public int? DistanceFactor { get; set; } [Display(Name = "Distance Move Unable to Match by 1 Tick"), Required] public bool? DistanceMoveUnableToMatch { get; set; } [Display(Name = "Distance Pixel Distance Tolerance"), Required] public int? DistancePixelDistanceTolerance { get; set; } @@ -99,6 +100,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults)); if (configuration.CrossDirectoryMaxItemsInDistanceCollection is null) throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection)); + if (configuration.DeletePossibleDuplicates is null) + throw new NullReferenceException(nameof(configuration.DeletePossibleDuplicates)); if (configuration.DistanceFactor is null) throw new NullReferenceException(nameof(configuration.DistanceFactor)); if (configuration.DistanceMoveUnableToMatch is null) @@ -215,6 +218,7 @@ public class Configuration configuration.CheckDFaceAndUpWriteDates.Value, configuration.CheckJsonForDistanceResults.Value, configuration.CrossDirectoryMaxItemsInDistanceCollection.Value, + configuration.DeletePossibleDuplicates.Value, configuration.DistanceFactor.Value, configuration.DistanceMoveUnableToMatch.Value, configuration.DistancePixelDistanceTolerance.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 4b9bab7..a70fe59 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -12,6 +12,7 @@ public class Configuration public bool CheckDFaceAndUpWriteDates { init; get; } public bool CheckJsonForDistanceResults { init; get; } public int CrossDirectoryMaxItemsInDistanceCollection { init; get; } + public bool DeletePossibleDuplicates { get; internal set; } public int DistanceFactor { init; get; } public bool DistanceMoveUnableToMatch { init; get; } public int DistancePixelDistanceTolerance { init; get; } @@ -81,6 +82,7 @@ public class Configuration bool checkDFaceAndUpWriteDates, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, + bool deletePossibleDuplicates, int distanceFactor, bool distanceMoveUnableToMatch, int distancePixelDistanceTolerance, @@ -149,6 +151,7 @@ public class Configuration CheckDFaceAndUpWriteDates = checkDFaceAndUpWriteDates; CheckJsonForDistanceResults = checkJsonForDistanceResults; CrossDirectoryMaxItemsInDistanceCollection = crossDirectoryMaxItemsInDistanceCollection; + DeletePossibleDuplicates = deletePossibleDuplicates; DistanceFactor = distanceFactor; DistanceMoveUnableToMatch = distanceMoveUnableToMatch; DistancePixelDistanceTolerance = distancePixelDistanceTolerance; diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index 90a8150..a5dcde5 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -10,6 +10,7 @@ }, "Windows": { "Configuration": { + "DeletePossibleDuplicates": false, "DistanceRenameToMatch": true, "DistanceMoveUnableToMatch": true, "PersonCharacters": "!#]^_`~+", @@ -32,13 +33,13 @@ "Julie" ], "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ - "7680 x 4320" + "Original" ], "LoadOrCreateThenSaveImageFacesResultsForOutputResolutions": [ - "7680 x 4320" + "Original" ], "OutputResolutions": [ - "7680 x 4320" + "Original" ], "PropertyContentCollectionFiles": [], "RangeDaysDeltaTolerance": [ @@ -62,13 +63,13 @@ 100 ], "SaveFaceDistancesForOutputResolutions": [ - "7680 x 4320" + "Original" ], "SaveFaceLandmarkForOutputResolutions": [], "SaveFilteredOriginalImagesFromJLinksForOutputResolutions": [], "SaveMappedForOutputResolutions": [], "SaveRandomForOutputResolutions": [ - "7680 x 4320" + "Original" ], "SaveShortcutsForOutputResolutions": [], "IgnoreRelativePaths": [ diff --git a/Instance/appsettings.json b/Instance/appsettings.json index c51a660..ed6dd6e 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -54,6 +54,7 @@ "CheckJsonForDistanceResults": false, "CrossDirectoryMaxItemsInDistanceCollection": 7, "DateGroup": "2022-12-30", + "DeletePossibleDuplicates": false, "DistanceFactor": 8, "DistanceMoveUnableToMatch": false, "DistancePixelDistanceTolerance": 1, @@ -200,6 +201,7 @@ ".TIFF" ], "ValidResolutions": [ + "Original", "176 x 176", "256 x 256", "353 x 353", diff --git a/Resize/Models/_C_Resize.cs b/Resize/Models/_C_Resize.cs index 18d44a1..64bac97 100644 --- a/Resize/Models/_C_Resize.cs +++ b/Resize/Models/_C_Resize.cs @@ -14,7 +14,7 @@ namespace View_by_Distance.Resize.Models; /// // Dictionary /// -public class C_Resize +public class C_Resize : Shared.Models.Methods.IResize { public List AngleBracketCollection { get; } @@ -22,6 +22,7 @@ public class C_Resize protected readonly string _FileNameExtension; public string FileNameExtension => _FileNameExtension; + private readonly string _Original; private readonly int _TempResolutionWidth; private readonly int _TempResolutionHeight; private readonly string[] _ValidResolutions; @@ -39,6 +40,7 @@ public class C_Resize public C_Resize(bool forceResizeLastWriteTimeToCreationTime, bool overrideForResizeImages, bool propertiesChangedForResize, string[] validResolutions, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) { + _Original = "Original"; _TempResolutionWidth = 3; _TempResolutionHeight = 4; _OutputResolutionWidthIndex = 0; @@ -175,9 +177,8 @@ public class C_Resize } } - private byte[] SaveResizedSubfile3(MappingFromItem mappingFromItem, int[] resize, bool returnAndDoNotWrite, byte[] bytes) + private void SaveResizedSubfile3(MappingFromItem mappingFromItem, int[] resize, byte[] bytes) { - byte[] results; Bitmap bitmap; int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; using Bitmap temp = new(mappingFromItem.ImageFileHolder.FullName, useIcm: false); @@ -215,21 +216,13 @@ public class C_Resize default: break; } - if (returnAndDoNotWrite) - results = GetBitmapData(bitmap); - else - { - results = Array.Empty(); - CopyPropertyItems(bytes, propertyItems, bitmap); - bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters); - } + CopyPropertyItems(bytes, propertyItems, bitmap); + bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters); bitmap.Dispose(); - return results; } - private byte[] SaveResizedSubfile5(MappingFromItem mappingFromItem, int[] resize, bool returnAndDoNotWrite, byte[] bytes) + private void SaveResizedSubfile5(MappingFromItem mappingFromItem, int[] resize, byte[] bytes) { - byte[] results; Bitmap bitmap; using Bitmap temp = new(mappingFromItem.ImageFileHolder.FullName, useIcm: false); PropertyItem[] propertyItems = temp.PropertyItems; @@ -279,24 +272,16 @@ public class C_Resize { using (Graphics graphics = Graphics.FromImage(preRotated)) graphics.DrawImage(bitmap, new Rectangle(0, 0, outputResolutionWidth, outputResolutionHeight), rectangle, GraphicsUnit.Pixel); - if (returnAndDoNotWrite) - results = GetBitmapData(bitmap); - else - { - results = Array.Empty(); - CopyPropertyItems(bytes, propertyItems, bitmap); - bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters); - } + CopyPropertyItems(bytes, propertyItems, bitmap); + bitmap.Save(mappingFromItem.ResizedFileHolder.FullName, _ImageCodecInfo, _EncoderParameters); } bitmap.Dispose(); - return results; } #pragma warning restore CA1416 - private byte[] SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize, bool returnAndDoNotWrite) + private void SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize) { - byte[] results; // string subFile, Shared.Models.Property property, Shared.Models.FileHolder? fileHolder string dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat(); DateTime dateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property); @@ -305,43 +290,37 @@ public class C_Resize if (_ASCIIEncoding.GetString(bytes, 0, bytes.Length) != dateTimeValue) throw new Exception(); if (resize.Length == 3) - results = SaveResizedSubfile3(mappingFromItem, resize, returnAndDoNotWrite, bytes); + SaveResizedSubfile3(mappingFromItem, resize, bytes); else if (resize.Length == 5) - results = SaveResizedSubfile5(mappingFromItem, resize, returnAndDoNotWrite, bytes); + SaveResizedSubfile5(mappingFromItem, resize, bytes); else throw new Exception(); - return results; } - public byte[] GetResizedBytes(string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary imageResizeKeyValuePairs) + (int, int, int) Shared.Models.Methods.IResize.Get(string outputResolution, Dictionary outputResolutionToResize) { - byte[] results; - if (!imageResizeKeyValuePairs.ContainsKey(outputResolution)) - throw new Exception(); - int[] resize = imageResizeKeyValuePairs[outputResolution]; - int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; - int outputResolutionHeight = resize[_OutputResolutionHeightIndex]; - int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex]; - results = SaveResizedSubfile(property, mappingFromItem, resize, returnAndDoNotWrite: true); - subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); - return results; + int[] outputResolutionCollection = outputResolutionToResize[outputResolution]; + int outputResolutionWidth = outputResolutionCollection[0]; + int outputResolutionHeight = outputResolutionCollection[1]; + int outputResolutionOrientation = outputResolutionCollection[2]; + return new(outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); } - public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, string original, Dictionary imageResizeKeyValuePairs) + public void SaveResizedSubfile(Property.Models.Configuration configuration, string outputResolution, string cResultsFullGroupDirectory, List> subFileTuples, Item item, Shared.Models.Property property, MappingFromItem mappingFromItem, Dictionary outputResolutionToResize) { if (mappingFromItem.ResizedFileHolder is null) throw new NullReferenceException(nameof(mappingFromItem.ResizedFileHolder)); - if (!imageResizeKeyValuePairs.ContainsKey(original)) + if (!outputResolutionToResize.ContainsKey(_Original)) throw new Exception(); - if (!imageResizeKeyValuePairs.ContainsKey(outputResolution)) + if (!outputResolutionToResize.ContainsKey(outputResolution)) throw new Exception(); FileInfo fileInfo = new(mappingFromItem.ResizedFileHolder.FullName); bool check = false; - int[] resize = imageResizeKeyValuePairs[outputResolution]; + int[] resize = outputResolutionToResize[outputResolution]; int outputResolutionWidth = resize[_OutputResolutionWidthIndex]; int outputResolutionHeight = resize[_OutputResolutionHeightIndex]; int outputResolutionOrientation = resize[_OutputResolutionOrientationIndex]; - int[] originalCollection = imageResizeKeyValuePairs[original]; + int[] originalCollection = outputResolutionToResize[_Original]; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); if (_OverrideForResizeImages) @@ -367,7 +346,7 @@ public class C_Resize check = true; if (check) { - _ = SaveResizedSubfile(property, mappingFromItem, resize, returnAndDoNotWrite: false); + SaveResizedSubfile(property, mappingFromItem, resize); item.SetResizedFileHolder(_FileNameExtension, Shared.Models.Stateless.Methods.IFileHolder.Refresh(mappingFromItem.ResizedFileHolder)); subFileTuples.Add(new Tuple(nameof(C_Resize), DateTime.Now)); } @@ -395,7 +374,7 @@ public class C_Resize return result; } - private Dictionary GetImageResizes(Shared.Models.Property property, List> metadataCollection, string original) + private Dictionary GetImageResizes(Shared.Models.Property property, List> metadataCollection) { Dictionary results = new(); int[] desired; @@ -412,12 +391,21 @@ public class C_Resize orientation = GetOrientation(metadataCollection); checkWidth = property.Width.Value; checkHeight = property.Height.Value; - results.Add(original, new int[] { checkWidth, checkHeight, orientation }); + if (!_ValidResolutions.Contains(_Original)) + results.Add(_Original, new int[] { checkWidth, checkHeight, orientation }); foreach (string validResolution in _ValidResolutions) { - desired = GetCollection(validResolution); - desiredWidth = desired[0]; - desiredHeight = desired[1]; + if (validResolution == _Original) + { + desiredWidth = checkWidth; + desiredHeight = checkHeight; + } + else + { + desired = GetCollection(validResolution); + desiredWidth = desired[0]; + desiredHeight = desired[1]; + } if (checkWidth <= desiredWidth && checkHeight <= desiredHeight) results.Add(validResolution, new int[] { checkWidth, checkHeight, orientation }); else @@ -447,9 +435,9 @@ public class C_Resize return result; } - public Dictionary GetResizeKeyValuePairs(Property.Models.Configuration configuration, string cResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, string original, List> metadataCollection, Shared.Models.Property property, MappingFromItem mappingFromItem) + public Dictionary GetResizeKeyValuePairs(Property.Models.Configuration configuration, string cResultsFullGroupDirectory, List> subFileTuples, List parseExceptions, List> metadataCollection, Shared.Models.Property property, MappingFromItem mappingFromItem) { - Dictionary results; + Dictionary? results; string json; string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata) }; List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); @@ -466,40 +454,32 @@ public class C_Resize fileInfo.Refresh(); } if (_PropertiesChangedForResize) - results = new(); + results = null; else if (!fileInfo.Exists) - results = new(); + results = null; else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old")) throw new ArgumentException("must be a *.json file"); else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) - results = new(); + results = null; else { json = File.ReadAllText(fileInfo.FullName); try { - Dictionary? keyValuePairs; - keyValuePairs = JsonSerializer.Deserialize>(json); - if (keyValuePairs is null) + results = JsonSerializer.Deserialize>(json); + if (results is null) throw new Exception(); - results = keyValuePairs; - if ((from l in results where l.Value[0] == l.Value[1] select true).Any()) - { - results = GetImageResizes(property, metadataCollection, original); - if (!(from l in results where l.Value[0] == l.Value[1] select true).Any()) - throw new Exception("Was square!"); - } subFileTuples.Add(new Tuple(nameof(C_Resize), fileInfo.LastWriteTime)); } catch (Exception) { - results = new(); + results = null; parseExceptions.Add(nameof(C_Resize)); } } - if (results is null || !results.Any()) + if (results is null) { - results = GetImageResizes(property, metadataCollection, original); + results = GetImageResizes(property, metadataCollection); json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); diff --git a/Shared/Models/Methods/IResize.cs b/Shared/Models/Methods/IResize.cs new file mode 100644 index 0000000..748b039 --- /dev/null +++ b/Shared/Models/Methods/IResize.cs @@ -0,0 +1,8 @@ +namespace View_by_Distance.Shared.Models.Methods; + +public interface IResize +{ + + (int, int, int) Get(string outputResolution, Dictionary outputResolutionToResize); + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/ILocation.cs b/Shared/Models/Stateless/Methods/ILocation.cs index f8ea238..4ec0bc8 100644 --- a/Shared/Models/Stateless/Methods/ILocation.cs +++ b/Shared/Models/Stateless/Methods/ILocation.cs @@ -30,12 +30,17 @@ public interface ILocation static List GetLocations(List mappingFromPhotoPrismCollection, List faces, List> containers) => Location.GetLocations(mappingFromPhotoPrismCollection, faces, containers); + Rectangle? TestStatic_GetNormalizedRectangle(int locationDigits, int normalizedRectangle) => + GetNormalizedRectangle(locationDigits, normalizedRectangle); + static Rectangle? GetNormalizedRectangle(int locationDigits, int normalizedRectangle) => + Location.GetNormalizedRectangle(locationDigits, normalizedRectangle.ToString()); + Rectangle? TestStatic_GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) => GetRectangle(checkRectangle, locationDigits, locationFactor, normalizedRectangle, outputResolution, useOldWay); static Rectangle? GetRectangle(Rectangle checkRectangle, int locationDigits, int locationFactor, int normalizedRectangle, Models.OutputResolution outputResolution, bool useOldWay) => Location.GetRectangle(checkRectangle, OutputResolution.Get(outputResolution).Height, locationDigits, locationFactor, normalizedRectangle.ToString(), OutputResolution.Get(outputResolution).Width, useOldWay); - Rectangle? TestStatic_GetRectangle(int height, int locationDigits, int locationFactor, int normalizedRectangle, int outputResolutionHeight, int outputResolutionWidth, int width) => + GetRectangle(height, locationDigits, locationFactor, normalizedRectangle, outputResolutionHeight, outputResolutionWidth, width); static Rectangle? GetRectangle(int height, int locationDigits, int locationFactor, int normalizedRectangle, int outputResolutionHeight, int outputResolutionWidth, int width) => Location.GetRectangle(height, locationDigits, locationFactor, normalizedRectangle.ToString(), outputResolutionHeight, outputResolutionWidth, width); diff --git a/Shared/Models/Stateless/Methods/Location.cs b/Shared/Models/Stateless/Methods/Location.cs index 53bc69f..b52cc39 100644 --- a/Shared/Models/Stateless/Methods/Location.cs +++ b/Shared/Models/Stateless/Methods/Location.cs @@ -140,7 +140,7 @@ internal abstract class Location return result; } - private static Rectangle? GetRectangle(int locationDigits, int height, string normalizedRectangle, int width) + internal static Rectangle? GetNormalizedRectangle(int locationDigits, string normalizedRectangle) { Rectangle? result; int length = (locationDigits - 1) / 4; @@ -159,10 +159,21 @@ internal abstract class Location if (!int.TryParse(segments[1], out int xNormalized) || !int.TryParse(segments[2], out int yNormalized) || !int.TryParse(segments[3], out int wNormalized) || !int.TryParse(segments[4], out int hNormalized)) result = null; else - { - decimal factor = 100; - result = new((int)(xNormalized / factor * width), (int)(yNormalized / factor * height), (int)(wNormalized / factor * width), (int)(hNormalized / factor * height)); - } + result = new(xNormalized, yNormalized, wNormalized, hNormalized); + } + return result; + } + + private static Rectangle? GetRectangle(int locationDigits, int height, string normalizedRectangle, int width) + { + Rectangle? result; + Rectangle? rectangle = GetNormalizedRectangle(locationDigits, normalizedRectangle); + if (rectangle is null) + result = null; + else + { + decimal factor = 100; + result = new((int)(rectangle.Value.X / factor * width), (int)(rectangle.Value.Y / factor * height), (int)(rectangle.Value.Width / factor * width), (int)(rectangle.Value.Height / factor * height)); } return result; } diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index d778153..9db9168 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -101,14 +101,13 @@ public class UnitTestResize Item item; bool reverse = false; FileHolder resizedFileHolder; - string original = "Original"; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; List parseExceptions = new(); bool isValidImageFormatExtension = true; Shared.Models.Property? property = null; - Dictionary imageResizeKeyValuePairs; + Dictionary outputResolutionToResize; List> subFileTuples = new(); List> metadataCollection; int length = _PropertyConfiguration.RootDirectory.Length; @@ -148,9 +147,9 @@ public class UnitTestResize item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); (int _, metadataCollection) = metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem); - imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item.Property, mappingFromItem); + outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); - resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, original, imageResizeKeyValuePairs); + resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); } } \ No newline at end of file diff --git a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs index 4accd81..abb981c 100644 --- a/TestsWithFaceRecognitionDotNet/UnitTestFace.cs +++ b/TestsWithFaceRecognitionDotNet/UnitTestFace.cs @@ -175,7 +175,6 @@ public class UnitTestFace string sourceDirectoryName = "zzz Portrait Innovations Files 2007"; Item item; bool reverse = false; - string original = "Original"; FileHolder resizedFileHolder; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; @@ -183,7 +182,7 @@ public class UnitTestFace List parseExceptions = new(); bool isValidImageFormatExtension = true; Shared.Models.Property? property = null; - Dictionary imageResizeKeyValuePairs; + Dictionary outputResolutionToResize; List> subFileTuples = new(); List> metadataCollection; int length = _PropertyConfiguration.RootDirectory.Length; @@ -223,9 +222,9 @@ public class UnitTestFace item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item); (int _, metadataCollection) = metadata.GetMetadataCollection(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, subFileTuples, parseExceptions, mappingFromItem); - imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, original, metadataCollection, item.Property, mappingFromItem); + outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); Assert.IsNotNull(mappingFromItem.ResizedFileHolder); - resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, original, imageResizeKeyValuePairs); + resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize); Image image = FaceRecognition.LoadImageFile(mappingFromItem.ResizedFileHolder.FullName); Assert.IsNotNull(image); (Model model, PredictorModel predictorModel, ModelParameter modelParameter) = GetModel(_Configuration);