Rename files to padded number string

This commit is contained in:
2023-07-09 23:36:39 -07:00
parent d7ed5d89d9
commit 818a1b0b38
60 changed files with 1118 additions and 1455 deletions

View File

@ -29,15 +29,12 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
- [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md)
- [import-know-faces-into-db](tasks/import-know-faces-into-db.md)
- [skip-metadata-load-after-first-each-day](tasks/skip-metadata-load-after-first-each-day.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
- [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md)
- [nef-support](tasks/nef-support.md)
## In Progress
- [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md)
- [nef-support](tasks/nef-support.md)
- [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md)
- [merge-kristy-files](tasks/merge-kristy-files.md)
- [set-date-taken-when-missing](tasks/set-date-taken-when-missing.md)
- [rename-files-to-padded-number-string](tasks/rename-files-to-padded-number-string.md)
## Done
@ -45,3 +42,6 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
- [run-scan-originals](tasks/run-scan-originals.md)
- [shrink-percent](tasks/shrink-percent.md)
- [setup-photo-prism-again-in-wsl-docker](tasks/setup-photo-prism-again-in-wsl-docker.md)
- [set-date-taken-when-missing](tasks/set-date-taken-when-missing.md)
- [rename-files-to-padded-number-string](tasks/rename-files-to-padded-number-string.md)
- [merge-kristy-files](tasks/merge-kristy-files.md)

View File

@ -1,10 +1,10 @@
---
created: 2023-06-18T20:29:10.288Z
updated: 2023-07-08T21:21:04.820Z
updated: 2023-07-09T23:00:08.674Z
assigned: ""
progress: 0
tags: []
status: "3-In Progress"
status: '3-In Progress'
type: kanbn
---

View File

@ -1,6 +1,6 @@
---
created: 2023-06-25T16:35:28.627Z
updated: 2023-07-08T21:44:14.665Z
updated: 2023-07-09T22:16:11.849Z
assigned: ""
progress: 0
tags: []
@ -23,4 +23,6 @@ return new(result, (from l in results orderby l.FileHolder.DirectoryName?.EndsWi
- [ ] Copy to each backup from question
- [x] Rotate the .jpg only
- [x] Use Rename console app to rename for storage
- [x] Set created date
- [ ] Verify
- [ ] Move to production ...

View File

@ -1,10 +1,10 @@
---
created: 2023-06-24T02:13:16.426Z
updated: 2023-07-08T21:21:06.222Z
updated: 2023-07-09T23:00:05.524Z
assigned: ""
progress: 0
tags: []
status: "3-In Progress"
status: '3-In Progress'
type: kanbn
---

View File

@ -1,12 +1,13 @@
---
created: 2023-07-08T21:26:25.403Z
updated: 2023-07-08T21:26:25.399Z
updated: 2023-07-10T06:35:46.076Z
assigned: ""
progress: 0
tags: []
type: note
---
# Photoview in docker for a viewer only
# Photoview in Docker for a Viewer Only
## Sub-Tasks

View File

@ -1,17 +1,22 @@
---
created: 2023-07-08T21:25:25.925Z
updated: 2023-07-08T21:45:42.263Z
updated: 2023-07-10T05:03:00.856Z
assigned: ""
progress: 0
tags: []
started: 2023-07-08T21:45:42.263Z
type: note
---
# Rename files to padded number string
# Rename Files to Padded Number String
## Sub-tasks
- [ ] ~~Go Back to Index for Sort~~
- [ ] New file for index to to id
- [ ] Count backwards
- [ ] Maybe skip some for scan images
- [ ] ~~New file for index to to id~~
- [ ] ~~Count backwards~~
- [ ] ~~Maybe skip some for scan images~~
- [Set Date Taken When Missing](set-date-taken-when-missing.md)
- [x] Rename production with padding names starting with one directory
- [x] Need equivalent to NameWithoutExtensionIsIdFormat method
- [x] Verify nothing broke (run from resize original now ... ?)

View File

@ -1,6 +1,6 @@
---
created: 2023-07-05T22:17:38.271Z
updated: 2023-07-08T21:47:12.461Z
updated: 2023-07-10T00:16:19.096Z
status: 2-Todo
type: kanbn
started: 2023-07-08T21:47:12.461Z
@ -8,6 +8,15 @@ started: 2023-07-08T21:47:12.461Z
# Set Date Taken When Missing
```c#
records = (from l in unordered orderby l.DateTime, l.FileHolder.Name.Length, l.FileHolder.Name select l).ToArray();
return new(result, (from l in results orderby l.FileHolder.CreationTime, l.FileHolder.FullName.Length descending select l).ToArray());
```
## Sub-tasks
- [ ] [ ]
- [x] Set just one directory with no original and re-run Instance to verify it doesn't break anything
- [x] Set just one directory with all original and re-run Instance to verify it doesn't break anything
- [?] Set just one directory with mixed original and re-run Instance to verify it doesn't break anything
- [x] Set all and re-run Instance to verify it doesn't break anything
- [ ] Review above lines

View File

@ -1,10 +1,10 @@
---
created: 2023-06-23T13:56:11.956Z
updated: 2023-07-08T21:21:06.224Z
updated: 2023-07-09T23:00:03.100Z
assigned: ""
progress: 0
tags: []
status: "3-In Progress"
status: '3-In Progress'
type: kanbn
---

View File

@ -88,7 +88,6 @@
"PopulatePropertyId": true,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -120,36 +119,6 @@
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
],
"VerifyToSeason": [
". 2000",
". 2001",

View File

@ -122,34 +122,6 @@
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"VerifyToSeason": [
". 2000",
". 2001",

View File

@ -70,7 +70,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -94,36 +93,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -51,6 +51,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -45,6 +45,7 @@ public class DateGroup
if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!");
long ticks = DateTime.Now.Ticks;
Metadata.Models.B_Metadata metadata = new(propertyConfiguration);
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles)
File.Delete(dbFile);
@ -65,7 +66,7 @@ public class DateGroup
throw new Exception();
if (propertyConfiguration.PopulatePropertyId && (configuration.ByCreateDateShortcut || configuration.ByHash) && Shared.Models.Stateless.Methods.IProperty.Any(containers))
{
propertyLogic.SavePropertyParallelWork(ticks, t, containers);
propertyLogic.SavePropertyParallelWork(ticks, metadata, t, containers);
if (appSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(A_Property.SavePropertyParallelWork));
if (propertyLogic.ExceptionsDirectories.Any())

View File

@ -69,7 +69,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/phares/Pictures",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -95,36 +94,6 @@
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
],
"VerifyToSeason": [
". 2000",
". 2001",

View File

@ -71,7 +71,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -95,36 +94,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -66,7 +66,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -90,36 +89,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -37,6 +37,7 @@
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>

View File

@ -7,6 +7,7 @@ using System.Reflection;
using System.Text;
using System.Text.Json;
using View_by_Distance.Drag.Drop.Set.Item.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless;
using View_by_Distance.Shared.Models.Stateless.Methods;
@ -15,6 +16,14 @@ namespace View_by_Distance.Drag.Drop.Set.Item;
public partial class DragDropSetPropertyItem : Form
{
private record Record(FileHolder FileHolder,
bool IsIgnoreExtension,
bool IsValidImageFormatExtension,
int Id,
DateTime? DateTimeOriginal,
short? PropertyItemType,
string? Value);
private readonly ILogger _Logger;
private readonly TextBox _PathTextBox;
private readonly TextBox _JsonTextBox;
@ -23,6 +32,7 @@ public partial class DragDropSetPropertyItem : Form
private readonly ProgressBar _ProgressBar;
private readonly string _WorkingDirectory;
private readonly IsEnvironment _IsEnvironment;
private readonly Property.Models.Configuration _PropertyConfiguration;
public DragDropSetPropertyItem()
{
@ -50,6 +60,9 @@ public partial class DragDropSetPropertyItem : Form
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
logger = Log.ForContext<DragDropSetPropertyItem>();
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
_PropertyConfiguration = propertyConfiguration;
propertyConfiguration.Update();
logger.Information("Complete");
_Logger = logger;
_AppSettings = appSettings;
@ -102,18 +115,28 @@ public partial class DragDropSetPropertyItem : Form
_JsonTextBox.Text = message;
}
private static List<(string, int, DateTime?, short?, string?)> GetCollection(ASCIIEncoding asciiEncoding, int tagId, List<string> files)
private List<Record> GetRecords(ASCIIEncoding asciiEncoding, int tagId, List<string> files)
{
List<(string, int, DateTime?, short?, string?)> results = new();
List<Record> results = new();
int? id;
string? value;
string? message;
FileHolder fileHolder;
bool isIgnoreExtension;
DateTime? dateTimeOriginal;
PropertyItem? propertyItem;
Shared.Models.Property property;
bool isValidImageFormatExtension;
foreach (string file in files)
{
property = Property.Models.A_Property.GetImageProperty(file);
if (property.Id is null)
fileHolder = new(file);
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
(dateTimeOriginal, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
if (message is not null)
throw new Exception(message);
if (id is null)
continue;
using Image image = Image.FromFile(file);
using Image image = Image.FromFile(fileHolder.FullName);
if (!image.PropertyIdList.Contains(tagId))
(propertyItem, value) = (null, null);
else
@ -131,36 +154,37 @@ public partial class DragDropSetPropertyItem : Form
value = null;
}
}
results.Add((file, property.Id.Value, property.DateTimeOriginal, propertyItem?.Type, value));
results.Add(new(fileHolder, isIgnoreExtension, isValidImageFormatExtension, id.Value, dateTimeOriginal, propertyItem?.Type, value));
}
if (files.Count != results.Count)
throw new NotSupportedException();
return results;
}
private void SetPropertyItem(string setTo, int tagId, short type, ConstructorInfo constructorInfo, List<(string, int, DateTime?, short?, string?)> collection)
private void SetPropertyItem(string setTo, int tagId, short type, ASCIIEncoding asciiEncoding, ConstructorInfo constructorInfo, List<Record> records)
{
int? id;
Bitmap bitmap;
string? message;
string checkFile;
PropertyItem? propertyItem;
Shared.Models.Property property;
foreach ((string file, int id, DateTime? dateTimeOriginal, short? propertyItemType, string? value) in collection)
foreach (Record record in records)
{
if (propertyItemType is not null && propertyItemType.Value != type)
if (record.PropertyItemType is not null && record.PropertyItemType.Value != type)
throw new NotSupportedException();
if ((dateTimeOriginal is null || !string.IsNullOrEmpty(value) || value == setTo) && !_AppSettings.IgnoreRulesKeyWords.Contains(setTo))
if ((record.DateTimeOriginal is null || !string.IsNullOrEmpty(record.Value) || record.Value == setTo) && !_AppSettings.IgnoreRulesKeyWords.Contains(setTo))
continue;
checkFile = $"{file}.exif";
propertyItem = IProperty.GetPropertyItem(constructorInfo, tagId, type, setTo);
bitmap = new(file);
checkFile = $"{record.FileHolder.FullName}.exif";
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, tagId, type, setTo);
bitmap = new(record.FileHolder.FullName);
bitmap.SetPropertyItem(propertyItem);
bitmap.Save(checkFile);
bitmap.Dispose();
property = Property.Models.A_Property.GetImageProperty(checkFile);
if (property.Id is null || property.Id.Value != id)
(_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, record.FileHolder, record.IsIgnoreExtension, record.IsValidImageFormatExtension, asciiEncoding);
if (id is null || id.Value != record.Id)
throw new NotSupportedException();
File.Delete(file);
File.Move(checkFile, file);
File.Delete(record.FileHolder.FullName);
File.Move(checkFile, record.FileHolder.FullName);
}
}
@ -170,11 +194,11 @@ public partial class DragDropSetPropertyItem : Form
ASCIIEncoding asciiEncoding = new();
int xpKeywords = (int)IExif.Tags.XPKeywords;
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
List<(string, int, DateTime?, short?, string?)> collection = GetCollection(asciiEncoding, xpKeywords, files);
if (!collection.Any())
List<Record> records = GetRecords(asciiEncoding, xpKeywords, files);
if (!records.Any())
SetMessage("No data");
else
SetPropertyItem(setTo, xpKeywords, type, constructorInfo, collection);
SetPropertyItem(setTo, xpKeywords, type, asciiEncoding, constructorInfo, records);
}
private void SetPropertyItem(string[] paths, string setTo)

View File

@ -50,5 +50,48 @@
"ValidKeyWords": [
"Review"
],
"WorkingDirectoryName": "PharesApps"
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"DateGroup": "dd514b88",
"DiffPropertyDirectory": "",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 10,
"OutputExtension": ".jpg",
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": true,
"PropertiesChangedForProperty": false,
"ResultAllInOne": "_ _ _",
"ResultAllInOneSubdirectoryLength": 2,
"ResultCollection": "[]",
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"IgnoreExtensions": [
".gif",
".GIF",
".nef",
".NEF",
".pdf",
".PDF"
],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}
}

View File

@ -68,7 +68,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -92,36 +91,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -190,11 +190,11 @@ public class D_Face
{
using (graphics = Graphics.FromImage(bitmap))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
propertyItem = Shared.Models.Stateless.Methods.IProperty.GetPropertyItem(_ConstructorInfo, fileSource, type, locationJson);
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, fileSource, type, locationJson);
bitmap.SetPropertyItem(propertyItem);
propertyItem = Shared.Models.Stateless.Methods.IProperty.GetPropertyItem(_ConstructorInfo, artist, type, outputResolutionJson);
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, artist, type, outputResolutionJson);
bitmap.SetPropertyItem(propertyItem);
propertyItem = Shared.Models.Stateless.Methods.IProperty.GetPropertyItem(_ConstructorInfo, userComment, type, faceEncodingJson);
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(_ConstructorInfo, userComment, type, faceEncodingJson);
bitmap.SetPropertyItem(propertyItem);
bitmap.Save(fileInfo.FullName, _ImageCodecInfo, _EncoderParameters);
}

View File

@ -16,6 +16,7 @@ using View_by_Distance.Property.Models;
using View_by_Distance.Resize.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless.Methods;
using WindowsShortcutFactory;
namespace View_by_Distance.Instance;
@ -126,9 +127,9 @@ public partial class DlibDotNet
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception();
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}"));
(_GenealogicalDataCommunicationHeaderLines, Dictionary<string, List<string>> individuals, _GenealogicalDataCommunicationFooterLines) = Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true);
_PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
(_GenealogicalDataCommunicationHeaderLines, Dictionary<string, List<string>> individuals, _GenealogicalDataCommunicationFooterLines) = IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true);
_PersonContainers = IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals);
VerifyPersonContainersDisplayDirectoryAllFiles();
}
{
@ -321,9 +322,9 @@ public partial class DlibDotNet
eyeα = α is null ? null : (int)Math.Round(Math.Abs(α.Value));
}
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
faceAreaPermyriad = Shared.Models.Stateless.Methods.IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution);
faceAreaPermyriad = IMapping.GetAreaPermyriad(_Configuration.FaceAreaPermyriad, face.Location, face.OutputResolution);
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
@ -356,7 +357,7 @@ public partial class DlibDotNet
else
{
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, Shared.Models.Stateless.ILocation.Digits);
deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, Shared.Models.Stateless.ILocation.Digits);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
@ -413,12 +414,13 @@ public partial class DlibDotNet
List<string> parseExceptions = new();
List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection;
string[] changesFrom = new string[] { nameof(A_Property) };
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
if (item.Property is null || item.Property.Id is null || item.Any())
{
LogItemPropertyIsNull(item);
int? propertyHashCode = item.Property?.GetHashCode();
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
if (propertyHashCode is null)
{
@ -438,9 +440,13 @@ public partial class DlibDotNet
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
else
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime));
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
bool nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(item.ImageFileHolder);
bool nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(item.ImageFileHolder, sortOrderOnlyLengthIndex);
if (nameWithoutExtensionIsIdFormat && item.ImageFileHolder.NameWithoutExtension != item.Property.Id.ToString())
LogNameWithoutExtensionIsIdFormatBut(item);
if (nameWithoutExtensionIsPaddedIdFormat && item.ImageFileHolder.NameWithoutExtension.EndsWith(item.Property.Id.Value.ToString()[1..]))
LogNameWithoutExtensionIsIdFormatBut(item);
if (_BlurHasher is not null && resizedFileHolder.Exists && item.Property.Width is not null && item.Property.Width.Value > 4 && _Configuration.SaveBlurHashForOutputResolutions.Contains(outputResolution))
{
string? file = _BlurHasher.GetFile(resizedFileHolder);
@ -451,8 +457,8 @@ public partial class DlibDotNet
if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
(int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
(int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem);
if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection));
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem);
@ -794,10 +800,10 @@ public partial class DlibDotNet
private void MapLogic(long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary<long, List<int>> personKeyToIds, List<Shared.Models.Face> distinctFilteredFaces, Mapping[] distinctFilteredMappingCollection, int totalNotMapped)
{
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()");
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()");
string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, "[()]");
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, "[]", _Configuration.PropertyConfiguration.ResultAllInOne);
string dFacesCollectionDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultCollection, _Configuration.PropertyConfiguration.ResultAllInOne);
if (distinctFilteredMappingCollection.Any())
{
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(d2FacePartsContentDirectory, ticks);
@ -871,24 +877,29 @@ public partial class DlibDotNet
private static void LookForAbandoned(List<int> distinctFilteredIds, string directory, string directoryName)
{
string fileNameWithoutExtension;
bool nameWithoutExtensionIsIdFormat;
List<string> renameCollection = new();
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray();
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)));
if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension))
nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat)
continue;
if (!Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension))
if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension))
continue;
renameCollection.Add(file);
}
if (renameCollection.Any())
{
if (directoryName.Length == 2)
Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}");
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[0]}abd{directoryName[^1]}");
else if (directoryName.Length == 4)
Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}");
IDirectory.MoveFiles(renameCollection, directoryName, $"{directoryName[..2]}abd{directoryName[^2..]}");
else
throw new NotSupportedException();
}
@ -906,7 +917,7 @@ public partial class DlibDotNet
}
}
private static void LookForAbandoned(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
private void LookForAbandoned(ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers, List<int> distinctFilteredIds)
{
List<string> renameCollection = new();
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in idToLocationContainers)
@ -921,7 +932,7 @@ public partial class DlibDotNet
}
}
if (renameCollection.Any())
Shared.Models.Stateless.Methods.IDirectory.MoveFiles(renameCollection, "()", "(abd)");
IDirectory.MoveFiles(renameCollection, _Configuration.PropertyConfiguration.ResultContent, "(abd)");
}
private void LookForAbandoned(string bResultsFullGroupDirectory, Container[] containers, ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers)
@ -994,7 +1005,7 @@ public partial class DlibDotNet
{
if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue;
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder);
mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder);
if (distinctItems)
{
if (distinct.Contains(item.Property.Id.Value))
@ -1137,6 +1148,7 @@ public partial class DlibDotNet
private void Search(long ticks, string argZero, string propertyRoot)
{
int t;
int count;
string message;
Container[] containers;
A_Property propertyLogic;
@ -1151,26 +1163,53 @@ public partial class DlibDotNet
string fPhotoPrismContentDirectory;
const string fileSearchFilter = "*";
string fPhotoPrismSingletonDirectory;
bool filesCollectionCountIsOne = false;
List<string[]>? filesCollection = null;
const string directorySearchFilter = "*";
Dictionary<long, List<int>> personKeyToIds;
bool eLastWriteTimeTimeSpanIsMoreThen = false;
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection;
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}");
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()");
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "()");
fPhotoPrismSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), "{}");
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
List<string[]> filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_Configuration.PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
int count = filesCollection.Select(l => l.Length).Sum();
if (filesCollection.Count == 1)
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
TimeSpan eLastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(eDistanceContentDirectory).LastWriteTime.Ticks);
foreach (string outputResolution in _Configuration.OutputResolutions)
{
if (outputResolution.Any(l => char.IsNumber(l)))
continue;
eLastWriteTimeTimeSpanIsMoreThen = true;
if (eLastWriteTimeTimeSpan.TotalDays < 1)
break;
ProgressBar progressBar;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, new string[] { _Configuration.PropertyConfiguration.ResultContent });
filesCollection = IDirectory.GetFilesCollection(_Configuration.PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
count = filesCollection.Select(l => l.Length).Sum();
filesCollectionCountIsOne = filesCollection.Count == 1;
progressBar = new(count, message, options);
(string[] distinctDirectories, List<(FileHolder, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick());
progressBar.Dispose();
message = $") Copying to ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
progressBar = new(count, message, options);
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose();
break;
}
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
fPhotoPrismContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(F_PhotoPrism), _Configuration.PropertyConfiguration.ResultSingleton);
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), _Configuration.PropertyConfiguration.ResultSingleton);
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
if (filesCollectionCountIsOne)
{
if (filesCollection is null)
throw new NullReferenceException(nameof(filesCollection));
string resultsGroupDirectory;
a2PeopleContentDirectory = null;
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()");
fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()");
fPhotoPrismSingletonDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "{}");
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismSingletonDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultSingleton);
for (int i = 1; i < 10; i++)
{
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true);
@ -1182,31 +1221,25 @@ public partial class DlibDotNet
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
}
TimeSpan eLastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(eDistanceContentDirectory).LastWriteTime.Ticks);
if (eLastWriteTimeTimeSpanIsMoreThen)
{
foreach (string outputResolution in _Configuration.OutputResolutions)
{
if (outputResolution.Any(l => char.IsNumber(l)))
continue;
if (eLastWriteTimeTimeSpan.TotalDays < 1)
break;
ProgressBar progressBar;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
IReadOnlyDictionary<string, string[]> fileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, new string[] { _Configuration.PropertyConfiguration.ResultContent });
message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
progressBar = new(count, message, options);
(string[] distinctDirectories, List<(FileHolder, string)> toDoCollection) = Shared.Models.Stateless.Methods.IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, copyDuplicates: false, filesCollection, fileGroups[_Configuration.PropertyConfiguration.ResultContent], () => progressBar.Tick());
progressBar.Dispose();
message = $") Copying to ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
progressBar = new(count, message, options);
_ = Shared.Models.Stateless.Methods.IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
progressBar.Dispose();
filesCollection = IDirectory.GetFilesCollection(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent, _Configuration.PropertyConfiguration.ResultAllInOne), directorySearchFilter, fileSearchFilter);
count = filesCollection.Select(l => l.Length).Sum();
break;
}
}
if (filesCollection is null)
throw new NullReferenceException(nameof(filesCollection));
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
using (ProgressBar progressBar = new(2, message, options))
{
progressBar.Tick();
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
(t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollection);
@ -1215,11 +1248,11 @@ public partial class DlibDotNet
fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, new(_PersonContainers), ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory);
_PersonContainers.AddRange(Shared.Models.Stateless.Methods.IPersonContainer.GetNonSpecificPeopleCollection(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFirstYear, _Configuration.PersonCharacters.ToArray(), _PersonContainers, ticks));
_PersonContainers.AddRange(IPersonContainer.GetNonSpecificPeopleCollection(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFirstYear, _Configuration.PersonCharacters.ToArray(), _PersonContainers, ticks));
containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
personKeyToIds = mapLogic.GetPersonKeyToIds();
if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && !string.IsNullOrEmpty(a2PeopleContentDirectory) && _GenealogicalDataCommunicationHeaderLines is not null && _GenealogicalDataCommunicationFooterLines is not null && _GenealogicalDataCommunicationHeaderLines.Any() && _GenealogicalDataCommunicationFooterLines.Any())
Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.CreateTree(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _Configuration.PropertyConfiguration.ResultAllInOne, _PersonContainers, _GenealogicalDataCommunicationHeaderLines, _GenealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds);
IGenealogicalDataCommunication.CreateTree(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _Configuration.PropertyConfiguration.ResultAllInOne, _PersonContainers, _GenealogicalDataCommunicationHeaderLines, _GenealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds);
ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers = mapLogic.GetIdToLocationContainers();
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, idToLocationContainers, mapLogic);
if (_Configuration.LookForAbandoned)
@ -1257,11 +1290,11 @@ public partial class DlibDotNet
continue;
if (!_IsEnvironment.Development)
{
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}"));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}"));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}"));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution))
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]"));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultCollection));
}
}
}

View File

@ -3,25 +3,21 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Instance.Models;
public class AppSettings
public record AppSettings(string Company,
int MaxDegreeOfParallelism,
string WorkingDirectoryName)
{
public string Company { init; get; }
public int MaxDegreeOfParallelism { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string company, int maxDegreeOfParallelism, string workingDirectoryName)
{
Company = company;
MaxDegreeOfParallelism = maxDegreeOfParallelism;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AppSettings))]
internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Instance.Models.Binder;
@ -16,7 +17,7 @@ public class AppSettings
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
string result = JsonSerializer.Serialize(this, BinderAppSettingsSourceGenerationContext.Default.AppSettings);
return result;
}
@ -36,9 +37,17 @@ public class AppSettings
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
#pragma warning disable IL3050, IL2026
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
#pragma warning restore IL3050, IL2026
result = Get(appSettings);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AppSettings))]
internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -121,7 +121,6 @@
"SortingMinimumToUseSigma": 10,
"TestDistanceResults": true,
"UseFilterTries": 0,
"WriteBitmapDataBytes": false,
"CopyFacesAndSaveFaceLandmarkForOutputResolutions": [],
"IgnoreExtensions": [
".gif",
@ -187,36 +186,6 @@
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
],
"ValidResolutions": [
"Original",
"176 x 176",

View File

@ -67,7 +67,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -91,36 +90,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -39,7 +39,7 @@
<PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -1,8 +1,12 @@
using MetadataExtractor;
using MetadataExtractor.Formats.Avi;
using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.QuickTime;
using System.Diagnostics;
using System.Text.Json;
using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Property.Models;
using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
@ -11,7 +15,7 @@ namespace View_by_Distance.Metadata.Models;
/// <summary>
// Dictionary<string, List<KeyValuePair<string, string>>>
/// </summary>
public class B_Metadata
public class B_Metadata : IMetadata<MetadataExtractor.Directory>
{
private readonly Serilog.ILogger? _Log;
@ -21,6 +25,16 @@ public class B_Metadata
private readonly IReadOnlyDictionary<string, string[]> _FileGroups;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions;
public B_Metadata(IPropertyConfiguration propertyConfiguration)
{
_PropertiesChangedForMetadata = false;
_Log = Serilog.Log.ForContext<B_Metadata>();
_PropertyConfiguration = propertyConfiguration;
_ForceMetadataLastWriteTimeToCreationTime = false;
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
_FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, null, new string[] { propertyConfiguration.ResultSingleton });
}
public B_Metadata(IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, string bResultsFullGroupDirectory)
{
_Log = Serilog.Log.ForContext<B_Metadata>();
@ -49,12 +63,12 @@ public class B_Metadata
List<string> tagNames = new();
int type = (int)IExif.Tags.Orientation;
string key = nameof(IExif.Tags.Orientation);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(subFile);
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(subFile);
foreach (MetadataExtractor.Directory directory in directories)
{
if (!results.ContainsKey(directory.Name))
results.Add(directory.Name, new());
foreach (MetadataExtractor.Tag tag in directory.Tags)
foreach (Tag tag in directory.Tags)
{
tagNames.Add(tag.Name);
if (string.IsNullOrEmpty(tag.Description))
@ -80,11 +94,10 @@ public class B_Metadata
return results;
}
public (int, List<KeyValuePair<string, string>>) GetMetadataCollection(List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Shared.Models.MappingFromItem mappingFromItem)
public (int, List<KeyValuePair<string, string>>) GetMetadataCollection(List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, string[] changesFrom, MappingFromItem mappingFromItem)
{
List<KeyValuePair<string, string>> results = new();
string json = string.Empty;
string[] changesFrom = new string[] { nameof(A_Property) };
Dictionary<string, List<KeyValuePair<string, string>>>? dictionary;
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList();
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_PropertyConfiguration.ResultAllInOneSubdirectoryLength, mappingFromItem.ImageFileHolder.Name);
@ -149,4 +162,104 @@ public class B_Metadata
return new(dictionary.Count, results);
}
(DateTime?, DateTime?[]) IMetadata<MetadataExtractor.Directory>.GetDateTimes(FileHolder fileHolder, IReadOnlyList<MetadataExtractor.Directory> directories)
{
List<DateTime?> results = new();
DateTime? result = null;
DateTime? dateTime;
DateTime checkDateTime;
string dateTimeFormat = Property.Models.Stateless.IProperty.DateTimeFormat();
ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().FirstOrDefault();
results.Add(fileHolder.CreationTime);
results.Add(fileHolder.LastWriteTime);
if (exifDirectoryBase is not null)
{
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime))
results.Add(checkDateTime);
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTime));
if (dateTime is not null)
results.Add(dateTime.Value);
}
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime))
results.Add(checkDateTime);
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeDigitized));
if (dateTime is not null)
results.Add(dateTime.Value);
}
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeOriginal));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
AviDirectory? aviDirectory = directories.OfType<AviDirectory>().FirstOrDefault();
if (aviDirectory is not null)
{
if (aviDirectory.TryGetDateTime(AviDirectory.TagDateTimeOriginal, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, aviDirectory.GetString(AviDirectory.TagDateTimeOriginal));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
QuickTimeMovieHeaderDirectory? quickTimeMovieHeaderDirectory = directories.OfType<QuickTimeMovieHeaderDirectory>().FirstOrDefault();
if (quickTimeMovieHeaderDirectory is not null)
{
if (quickTimeMovieHeaderDirectory.TryGetDateTime(QuickTimeMovieHeaderDirectory.TagCreated, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, quickTimeMovieHeaderDirectory.GetString(QuickTimeMovieHeaderDirectory.TagCreated));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
QuickTimeTrackHeaderDirectory? quickTimeTrackHeaderDirectory = directories.OfType<QuickTimeTrackHeaderDirectory>().FirstOrDefault();
if (quickTimeTrackHeaderDirectory is not null)
{
if (quickTimeTrackHeaderDirectory.TryGetDateTime(QuickTimeTrackHeaderDirectory.TagCreated, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Property.Models.Stateless.IProperty.GetDateTime(dateTimeFormat, quickTimeTrackHeaderDirectory.GetString(QuickTimeTrackHeaderDirectory.TagCreated));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
return new(result, results.ToArray());
}
}

View File

@ -3,11 +3,6 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods;
public interface IMetadata
{
(DateTime?, DateTime?[]) TestStatic_GetDateTimes(Shared.Models.FileHolder fileHolder, IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetDateTimes(fileHolder, directories);
static (DateTime?, DateTime?[]) GetDateTimes(Shared.Models.FileHolder fileHolder, IReadOnlyList<MetadataExtractor.Directory> directories) =>
Metadata.GetDateTimes(fileHolder, directories);
string? TestStatic_GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetModel(directories);
static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>

View File

@ -1,7 +1,5 @@
using MetadataExtractor;
using MetadataExtractor.Formats.Avi;
using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.QuickTime;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
@ -53,106 +51,6 @@ internal class Metadata
return result;
}
internal static (DateTime?, DateTime?[]) GetDateTimes(Shared.Models.FileHolder fileHolder, IReadOnlyList<MetadataExtractor.Directory> directories)
{
List<DateTime?> results = new();
DateTime? result = null;
DateTime? dateTime;
DateTime checkDateTime;
string dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().FirstOrDefault();
results.Add(fileHolder.CreationTime);
results.Add(fileHolder.LastWriteTime);
if (exifDirectoryBase is not null)
{
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime))
results.Add(checkDateTime);
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTime));
if (dateTime is not null)
results.Add(dateTime.Value);
}
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime))
results.Add(checkDateTime);
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeDigitized));
if (dateTime is not null)
results.Add(dateTime.Value);
}
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeOriginal));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
AviDirectory? aviDirectory = directories.OfType<AviDirectory>().FirstOrDefault();
if (aviDirectory is not null)
{
if (aviDirectory.TryGetDateTime(AviDirectory.TagDateTimeOriginal, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, aviDirectory.GetString(AviDirectory.TagDateTimeOriginal));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
QuickTimeMovieHeaderDirectory? quickTimeMovieHeaderDirectory = directories.OfType<QuickTimeMovieHeaderDirectory>().FirstOrDefault();
if (quickTimeMovieHeaderDirectory is not null)
{
if (quickTimeMovieHeaderDirectory.TryGetDateTime(QuickTimeMovieHeaderDirectory.TagCreated, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, quickTimeMovieHeaderDirectory.GetString(QuickTimeMovieHeaderDirectory.TagCreated));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
QuickTimeTrackHeaderDirectory? quickTimeTrackHeaderDirectory = directories.OfType<QuickTimeTrackHeaderDirectory>().FirstOrDefault();
if (quickTimeTrackHeaderDirectory is not null)
{
if (quickTimeTrackHeaderDirectory.TryGetDateTime(QuickTimeTrackHeaderDirectory.TagCreated, out checkDateTime))
{
result ??= checkDateTime;
results.Add(checkDateTime);
}
else
{
dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTime(dateTimeFormat, quickTimeTrackHeaderDirectory.GetString(QuickTimeTrackHeaderDirectory.TagCreated));
if (dateTime is not null)
{
result ??= dateTime.Value;
results.Add(dateTime.Value);
}
}
}
return new(result, results.ToArray());
}
internal static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories)
{
string? result;

View File

@ -67,7 +67,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -91,36 +90,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -45,7 +45,6 @@
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

@ -2,9 +2,11 @@ using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using ShellProgressBar;
using System.Text;
using View_by_Distance.Move.By.Id.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Move.By.Id;
@ -104,12 +106,14 @@ public class MoveById
int? id;
string? message;
string[] matches;
DateTime?[] dateTimes;
FileHolder fileHolder;
bool isIgnoreExtension;
const string jpeg = ".jpeg";
bool isValidImageFormatExtension;
ASCIIEncoding asciiEncoding = new();
bool nameWithoutExtensionIsIdFormat;
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
foreach (string file in allFiles)
{
progressBar.Tick();
@ -119,16 +123,17 @@ public class MoveById
if (allFiles.Contains($"{fileHolder.FullName}.id"))
continue;
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileHolder);
if (!isIgnoreExtension && isValidImageFormatExtension)
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
if (!isIgnoreExtension && !isValidImageFormatExtension)
{
if (fileHolder.ExtensionLowered == jpeg)
continue;
if (nameWithoutExtensionIsIdFormat)
if (nameWithoutExtensionIsIdFormat || nameWithoutExtensionIsPaddedIdFormat)
continue;
}
(_, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId);
(_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
if (id is null)
continue;
matches = (from l in allFiles where l.Contains($"{id}{fileHolder.ExtensionLowered}") select l).ToArray();

View File

@ -69,7 +69,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -93,36 +92,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -5,7 +5,9 @@ using ShellProgressBar;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.Text;
using View_by_Distance.Offset.Date.Time.Original.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless;
@ -14,6 +16,12 @@ namespace View_by_Distance.Offset.Date.Time.Original;
public class OffsetDateTimeOriginal
{
private record Record(FileHolder FileHolder,
bool IsIgnoreExtension,
bool IsValidImageFormatExtension,
int Id,
DateTime DateTime);
private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory;
private readonly Configuration _Configuration;
@ -60,23 +68,34 @@ public class OffsetDateTimeOriginal
{ }
}
private static List<(string, int, DateTime)> GetCollection(string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks)
private List<Record> GetRecords(ASCIIEncoding asciiEncoding, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks)
{
List<(string, int, DateTime)> results = new();
List<Record> results = new();
DateTime dateTime;
Shared.Models.Property property;
int? id;
string? message;
DateTime[] dateTimes;
FileHolder fileHolder;
bool isIgnoreExtension;
DateTime? dateTimeOriginal;
bool isValidImageFormatExtension;
string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
property = Property.Models.A_Property.GetImageProperty(file);
if (property.Id is null || property.DateTimeOriginal is null)
fileHolder = new(file);
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
(dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
if (message is not null)
throw new Exception(message);
if (id is null || dateTimeOriginal is null)
continue;
dateTime = property.DateTimeOriginal.Value.AddTicks(ticks);
dateTime = dateTimeOriginal.Value.AddTicks(ticks);
if (dateTime < minimumDateTime)
continue;
if (dateTime > maximumDateTime)
continue;
results.Add((file, property.Id.Value, property.DateTimeOriginal.Value.AddTicks(ticks)));
results.Add(new(fileHolder, isIgnoreExtension, isValidImageFormatExtension, id.Value, dateTimeOriginal.Value.AddTicks(ticks)));
}
if (files.Length != results.Count)
throw new Exception();
@ -85,14 +104,14 @@ public class OffsetDateTimeOriginal
#pragma warning disable CA1416
private static void DateFix(string sourceDirectory, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks)
private void DateFix(string sourceDirectory, ASCIIEncoding asciiEncoding, string checkDirectory, DateTime minimumDateTime, DateTime maximumDateTime, long ticks)
{
int? id;
Bitmap bitmap;
short type = 2;
string checkFile;
PropertyItem? propertyItem;
string? ticksDirectory = null;
Shared.Models.Property property;
int dateTimeOriginal = (int)IExif.Tags.DateTimeOriginal;
for (int i = 0; i < int.MaxValue; i++)
{
@ -104,26 +123,28 @@ public class OffsetDateTimeOriginal
}
ticks++;
}
List<(string, int, DateTime)> collection = GetCollection(checkDirectory, minimumDateTime, maximumDateTime, ticks);
List<Record> records = GetRecords(asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, ticks);
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
string message = nameof(OffsetDateTimeOriginal);
string? message = nameof(OffsetDateTimeOriginal);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ProgressBar progressBar = new(collection.Count, message, options);
foreach ((string file, int id, DateTime dateTime) in collection)
ProgressBar progressBar = new(records.Count, message, options);
foreach (Record record in records)
{
progressBar.Tick();
if (ticksDirectory is null)
throw new Exception();
checkFile = Path.Combine(ticksDirectory, Path.GetFileName(file));
checkFile = Path.Combine(ticksDirectory, record.FileHolder.Name);
if (File.Exists(checkFile))
continue;
propertyItem = Shared.Models.Stateless.Methods.IProperty.GetPropertyItem(constructorInfo, dateTimeOriginal, type, dateTime.ToString("yyyy:MM:dd HH:mm:ss"));
bitmap = new(file);
propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, dateTimeOriginal, type, record.DateTime.ToString("yyyy:MM:dd HH:mm:ss"));
bitmap = new(record.FileHolder.FullName);
bitmap.SetPropertyItem(propertyItem);
bitmap.Save(checkFile);
bitmap.Dispose();
property = Property.Models.A_Property.GetImageProperty(checkFile);
if (property.Id is null || property.Id.Value != id)
(_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, record.FileHolder, record.IsIgnoreExtension, record.IsValidImageFormatExtension, asciiEncoding);
if (message is not null)
throw new Exception(message);
if (id is null || id.Value != record.Id)
throw new Exception();
}
progressBar.Dispose();
@ -131,13 +152,14 @@ public class OffsetDateTimeOriginal
#pragma warning restore CA1416
private static void DateFix(ILogger log, string sourceDirectory)
private void DateFix(ILogger log, string sourceDirectory)
{
string checkDirectory;
ASCIIEncoding asciiEncoding = new();
long oneYearTicks = DateTime.MinValue.AddYears(1).Ticks;
checkDirectory = Path.Combine(sourceDirectory, oneYearTicks.ToString());
if (Directory.Exists(checkDirectory))
DateFix(sourceDirectory, checkDirectory, DateTime.MinValue, DateTime.MaxValue, new TimeSpan(oneYearTicks - DateTime.MinValue.Ticks).Ticks);
DateFix(sourceDirectory, asciiEncoding, checkDirectory, DateTime.MinValue, DateTime.MaxValue, new TimeSpan(oneYearTicks - DateTime.MinValue.Ticks).Ticks);
else
{
checkDirectory = Path.Combine(sourceDirectory, "1");
@ -160,16 +182,40 @@ public class OffsetDateTimeOriginal
log.Error("bad file(s) or target file(s) or maximum directory doesn't equal 1!");
else
{
int? badId;
int? targetId;
string? badMessage;
string? targetMessage;
DateTime[] badDateTimes;
bool badIsIgnoreExtension;
DateTime[] targetDateTimes;
bool targetIsIgnoreExtension;
DateTime? badDateTimeOriginal;
DateTime? targetDateTimeOriginal;
FileHolder badFileHolder = new(badFiles.First());
FileHolder targetFileHolder = new(targetFiles.First());
bool badIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(badFileHolder.ExtensionLowered);
bool targetIsValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(targetFileHolder.ExtensionLowered);
badIsIgnoreExtension = badIsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(badFileHolder.ExtensionLowered);
targetIsIgnoreExtension = targetIsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(targetFileHolder.ExtensionLowered);
DateTime minimumDateTime = DateTime.ParseExact(Path.GetFileName(minimumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None);
DateTime maximumDateTime = DateTime.ParseExact(Path.GetFileName(maximumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None).AddHours(23);
Shared.Models.Property badProperty = Property.Models.A_Property.GetImageProperty(badFiles.First());
Shared.Models.Property targetProperty = Property.Models.A_Property.GetImageProperty(targetFiles.First());
if (badProperty.DateTimeOriginal is null || targetProperty.DateTimeOriginal is null)
(badDateTimeOriginal, badDateTimes, badId, badMessage) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, badFileHolder, badIsIgnoreExtension, badIsValidImageFormatExtension, asciiEncoding);
if (badMessage is not null)
throw new Exception(badMessage);
if (!badDateTimes.Any() || badId is null)
throw new Exception(badMessage);
(targetDateTimeOriginal, targetDateTimes, targetId, targetMessage) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, targetFileHolder, targetIsIgnoreExtension, targetIsValidImageFormatExtension, asciiEncoding);
if (targetMessage is not null)
throw new Exception(targetMessage);
if (!targetDateTimes.Any() || targetId is null)
throw new Exception(targetMessage);
if (badDateTimeOriginal is null || targetDateTimeOriginal is null)
log.Error("Date is null!");
else
{
TimeSpan timeSpan = new(targetProperty.DateTimeOriginal.Value.Ticks - badProperty.DateTimeOriginal.Value.Ticks);
DateFix(sourceDirectory, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks);
TimeSpan timeSpan = new(targetDateTimeOriginal.Value.Ticks - badDateTimeOriginal.Value.Ticks);
DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks);
}
}
}

View File

@ -66,7 +66,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -90,36 +89,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -19,7 +19,6 @@
"ResultSingleton": "{}",
"RootDirectory": "/srv/samba/share",
"SaveDirectory": "/home/vscode",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -43,36 +42,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
},
@ -141,7 +110,6 @@
"ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"SaveDirectory": "D:/Tmp",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -165,36 +133,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
},

View File

@ -59,7 +59,6 @@
"PopulatePropertyId": false,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Pictures",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -111,36 +110,6 @@
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
],
"VerifyToSeason": [
". 2000",
". 2001",

View File

@ -1,14 +1,9 @@
using ShellProgressBar;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models;
@ -62,201 +57,7 @@ public class A_Property
return result;
}
#pragma warning disable CA1416
private static List<DateTime> GetMetadataDateTimesByPattern(string dateTimeFormat, FileHolder fileHolder)
{
List<DateTime> results = new();
try
{
DateTime checkDateTime;
DateTime kristy = new(1976, 3, 8);
IReadOnlyList<MetadataExtractor.Directory> directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
foreach (MetadataExtractor.Directory directory in directories)
{
foreach (MetadataExtractor.Tag tag in directory.Tags)
{
if (string.IsNullOrEmpty(tag.Description) || tag.Description.Length != dateTimeFormat.Length)
continue;
if (!DateTime.TryParseExact(tag.Description, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
continue;
if (checkDateTime < kristy)
continue;
results.Add(checkDateTime);
}
}
}
catch (Exception) { }
return results;
}
private static Shared.Models.Property GetImageProperty(FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, ASCIIEncoding asciiEncoding, bool writeBitmapDataBytes, string? angleBracket)
{
Shared.Models.Property result;
byte[] bytes;
string value;
long fileLength;
int? width = null;
int? height = null;
string? make = null;
string? model = null;
string dateTimeFormat;
DateTime checkDateTime;
DateTime? dateTime = null;
PropertyItem? propertyItem;
string? orientation = null;
DateTime? gpsDateStamp = null;
DateTime? dateTimeOriginal = null;
DateTime? dateTimeDigitized = null;
DateTime? dateTimeFromName = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder);
if (!isValidImageFormatExtension && isValidMetadataExtensions && fileHolder.Exists)
{
dateTimeFormat = "ddd MMM dd HH:mm:ss yyyy";
List<DateTime> dateTimes = GetMetadataDateTimesByPattern(dateTimeFormat, fileHolder);
if (dateTimes.Any())
dateTimeOriginal = dateTimes.Min();
}
else if (!isIgnoreExtension && isValidImageFormatExtension && fileHolder.Exists)
{
try
{
using Image image = Image.FromFile(fileHolder.FullName);
width = image.Width;
height = image.Height;
if (populateId && id is null)
{
using Bitmap bitmap = new(image);
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
int length = bitmapData.Stride * bitmap.Height;
bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
id ??= Shared.Models.Stateless.Methods.IProperty.GetDeterministicHashCode(bytes);
if (writeBitmapDataBytes && !string.IsNullOrEmpty(angleBracket))
{
FileInfo contentFileInfo = new(Path.Combine(angleBracket.Replace("<>", "()"), fileHolder.Name));
File.WriteAllBytes(Path.ChangeExtension(contentFileInfo.FullName, string.Empty), bytes);
}
}
dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTime = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeDigitized = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeOriginal = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
gpsDateStamp = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Make))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Make);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
make = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Model))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Model);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
model = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation);
if (propertyItem?.Value is not null)
{
value = BitConverter.ToInt16(propertyItem.Value, 0).ToString();
orientation = value;
}
}
}
catch (Exception) { }
}
else
dateTimeOriginal = null;
if (fileHolder.Length is null)
fileLength = 0;
else
fileLength = fileHolder.Length.Value;
if (fileHolder.CreationTime is null && property?.CreationTime is null)
throw new NullReferenceException(nameof(fileHolder.CreationTime));
if (fileHolder.LastWriteTime is null && property?.LastWriteTime is null)
throw new NullReferenceException(nameof(fileHolder.LastWriteTime));
if (fileHolder.CreationTime is not null && fileHolder.LastWriteTime is not null)
result = new(fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, fileHolder.LastWriteTime.Value, make, model, orientation, width);
else if (property is not null)
result = new(property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, property.LastWriteTime, make, model, orientation, width);
else
throw new NullReferenceException(nameof(property));
return result;
}
public static Shared.Models.Property GetImageProperty(string fileName)
{
int? id = null;
bool populateId = true;
string? angleBracket = null;
bool isIgnoreExtension = false;
bool writeBitmapDataBytes = false;
ASCIIEncoding asciiEncoding = new();
bool isValidMetadataExtensions = true;
FileHolder fileHolder = new(fileName);
bool isValidImageFormatExtension = true;
Shared.Models.Property? property = null;
Shared.Models.Property result = GetImageProperty(fileHolder, property, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, asciiEncoding, writeBitmapDataBytes, angleBracket);
return result;
}
#pragma warning restore CA1416
private Shared.Models.Property GetPropertyOfPrivate(Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidMetadataExtensions)
private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension)
{
Shared.Models.Property? result;
int? id = null;
@ -348,7 +149,7 @@ public class A_Property
if (result is null)
{
id ??= item.ImageFileHolder.Id;
result = GetImageProperty(item.ImageFileHolder, result, populateId, isIgnoreExtension, item.IsValidImageFormatExtension, isValidMetadataExtensions, id, _ASCIIEncoding, _Configuration.WriteBitmapDataBytes, angleBracket);
(_, _, result) = Stateless.Property.GetProperty(populateId, metadata, item.ImageFileHolder, result, isIgnoreExtension, item.IsValidImageFormatExtension, id, _ASCIIEncoding);
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
{
@ -377,18 +178,17 @@ public class A_Property
return result;
}
private void SavePropertyParallelForWork(string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
private void SavePropertyParallelForWork(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
{
Shared.Models.Property property;
List<string> parseExceptions = new();
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}");
if (item.IsValidImageFormatExtension && item.ImageFileHolder.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.ImageFileHolder.FullName != filteredSourceDirectoryFileExtensionLowered)
File.Move(item.ImageFileHolder.FullName, filteredSourceDirectoryFileExtensionLowered);
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.Property is null)
{
property = GetPropertyOfPrivate(item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
property = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (item)
@ -396,7 +196,7 @@ public class A_Property
}
}
private void SavePropertyParallelWork(int maxDegreeOfParallelism, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container container, List<Item> items, string message)
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container container, List<Item> items, string message)
{
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = new();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
@ -409,7 +209,7 @@ public class A_Property
long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now;
List<Tuple<string, DateTime>> collection;
SavePropertyParallelForWork(container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
SavePropertyParallelForWork(metadata, container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
if (i == 0 || sourceDirectoryChanges.Any())
progressBar.Tick();
lock (sourceDirectoryFileTuples)
@ -452,7 +252,7 @@ public class A_Property
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
}
public void SavePropertyParallelWork(long ticks, int t, Container[] containers)
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container[] containers)
{
if (_Log is null)
throw new NullReferenceException(nameof(_Log));
@ -478,7 +278,7 @@ public class A_Property
SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName);
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
message = $"{i + 1:000} [{container.Items.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
SavePropertyParallelWork(_MaxDegreeOfParallelism, exceptions, sourceDirectoryChanges, container, container.Items, message);
SavePropertyParallelWork(_MaxDegreeOfParallelism, metadata, exceptions, sourceDirectoryChanges, container, container.Items, message);
foreach (Exception exception in exceptions)
_Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception);
if (exceptions.Count == container.Items.Count)
@ -499,7 +299,7 @@ public class A_Property
}
}
public Shared.Models.Property GetProperty(Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
public Shared.Models.Property GetProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
{
Shared.Models.Property result;
bool angleBracketCollectionAny = _AngleBracketCollection.Any();
@ -509,9 +309,8 @@ public class A_Property
throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName));
SetAngleBracketCollection(item.ImageFileHolder.DirectoryName, !item.IsUniqueFileName);
}
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
result = GetPropertyOfPrivate(item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
result = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
if (!angleBracketCollectionAny)
_AngleBracketCollection.Clear();
return result;

View File

@ -27,9 +27,7 @@ public class Configuration
[Display(Name = "Result Singleton"), Required] public string ResultSingleton { get; set; }
[Display(Name = "Root Directory"), Required] public string RootDirectory { get; set; }
[Display(Name = "Valid Image Format Extensions"), Required] public string[] ValidImageFormatExtensions { get; set; }
[Display(Name = "Valid Metadata Extensions"), Required] public string[] ValidMetadataExtensions { get; set; }
[Display(Name = "Verify to Season"), Required] public string[] VerifyToSeason { get; set; }
[Display(Name = "Write Bitmap Data Bytes"), Required] public bool? WriteBitmapDataBytes { get; set; }
#nullable restore
@ -62,12 +60,9 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.ResultContent));
if (configuration.ResultSingleton is null)
throw new NullReferenceException(nameof(configuration.ResultSingleton));
if (configuration.WriteBitmapDataBytes is null)
throw new NullReferenceException(nameof(configuration.WriteBitmapDataBytes));
configuration.IgnoreExtensions ??= Array.Empty<string>();
configuration.PropertyContentCollectionFiles ??= Array.Empty<string>();
configuration.ValidImageFormatExtensions ??= Array.Empty<string>();
configuration.ValidMetadataExtensions ??= Array.Empty<string>();
configuration.VerifyToSeason ??= Array.Empty<string>();
result = new(configuration.DateGroup,
configuration.FileNameDirectorySeparator,
@ -86,9 +81,7 @@ public class Configuration
configuration.ResultSingleton,
configuration.RootDirectory,
configuration.ValidImageFormatExtensions,
configuration.ValidMetadataExtensions,
configuration.VerifyToSeason,
configuration.WriteBitmapDataBytes.Value);
configuration.VerifyToSeason);
return result;
}

View File

@ -34,8 +34,6 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration
public string ResultContent { init; get; }
public string ResultSingleton { init; get; }
public string[] ValidImageFormatExtensions { init; get; }
public string[] ValidMetadataExtensions { init; get; }
public bool WriteBitmapDataBytes { init; get; }
[JsonConstructor]
public Configuration(string dateGroup,
@ -55,9 +53,7 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration
string resultSingleton,
string rootDirectory,
string[] validImageFormatExtensions,
string[] validMetadataExtensions,
string[] verifyToSeason,
bool writeBitmapDataBytes)
string[] verifyToSeason)
{
DateGroup = dateGroup;
FileNameDirectorySeparator = fileNameDirectorySeparator;
@ -76,8 +72,6 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration
ResultSingleton = resultSingleton;
_RootDirectory = rootDirectory;
ValidImageFormatExtensions = validImageFormatExtensions;
ValidMetadataExtensions = validMetadataExtensions;
WriteBitmapDataBytes = writeBitmapDataBytes;
}
public override string ToString()
@ -109,8 +103,6 @@ public class Configuration : Shared.Models.Properties.IPropertyConfiguration
throw new NullReferenceException(nameof(propertyConfiguration.PropertyContentCollectionFiles));
if (propertyConfiguration.ValidImageFormatExtensions is null || !propertyConfiguration.ValidImageFormatExtensions.Any())
throw new NullReferenceException(nameof(propertyConfiguration.ValidImageFormatExtensions));
if (propertyConfiguration.ValidMetadataExtensions is null || !propertyConfiguration.ValidMetadataExtensions.Any())
throw new NullReferenceException(nameof(propertyConfiguration.ValidMetadataExtensions));
if (propertyConfiguration is null)
throw new NullReferenceException(nameof(propertyConfiguration));
if (string.IsNullOrEmpty(propertyConfiguration.DateGroup))

View File

@ -0,0 +1,51 @@
using System.Drawing.Imaging;
using System.Reflection;
using System.Text;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Property.Models.Stateless;
public interface IProperty
{
string TestStatic_DateTimeFormat() =>
DateTimeFormat();
static string DateTimeFormat() =>
"yyyy:MM:dd HH:mm:ss";
int TestStatic_GetDeterministicHashCode(byte[] value) =>
GetDeterministicHashCode(value);
static int GetDeterministicHashCode(byte[] value) =>
Property.GetDeterministicHashCode(value);
byte[] TestStatic_GetBytes(string value) =>
GetBytes(value);
static byte[] GetBytes(string value) =>
Property.GetBytes(value);
DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
GetDateTime(dateTimeFormat, value);
static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
Property.GetDateTime(dateTimeFormat, value);
PropertyItem TestStatic_GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
GetPropertyItem(constructorInfo, id, type, value);
static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
Property.GetPropertyItem(constructorInfo, id, type, value);
(string?, DateTime[], Shared.Models.Property) TestStatic_GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, Shared.Models.FileHolder fileHolder, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
GetProperty(populateId, metadata, fileHolder, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, Shared.Models.FileHolder fileHolder, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding) =>
Property.GetProperty(populateId, metadata, fileHolder, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
(DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, Shared.Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
Get(populateId, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
static (DateTime?, DateTime[], int?, string?) Get(bool populateId, Shared.Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
Property.Get(populateId, null, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
(DateTime?, DateTime[], int?, string?) TestStatic_Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, Shared.Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
Get(populateId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, Shared.Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding) =>
Property.Get(populateId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
}

View File

@ -0,0 +1,395 @@
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models.Stateless;
internal class Property
{
internal static int GetDeterministicHashCode(byte[] value)
{
int result;
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
result = hash1 + (hash2 * 1566083941);
}
return result;
}
#pragma warning disable CA1416
internal static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value)
{
PropertyItem result = (PropertyItem)constructorInfo.Invoke(null);
int length;
byte[] bytes;
if (type == 2)
{
bytes = GetBytes(value);
length = value.Length + 1;
}
else if (type == 1)
{
bytes = Encoding.Unicode.GetBytes($"{value}\0");
length = bytes.Length;
}
else
throw new NotSupportedException();
result.Id = id;
result.Len = length;
result.Type = type;
result.Value = bytes;
return result;
}
#pragma warning restore CA1416
internal static byte[] GetBytes(string value)
{
byte[] results = new byte[value.Length + 1];
for (int i = 0; i < value.Length; i++)
results[i] = (byte)value[i];
results[value.Length] = 0x00;
return results;
}
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
{
DateTime? result;
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
result = dateTime;
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
result = dateTime;
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
result = dateTime;
else
result = null;
return result;
}
private static List<DateTime> GetDateTimes(DateTime?[] metadataDateTimes)
{
List<DateTime> results = new();
foreach (DateTime? dateTime in metadataDateTimes)
{
if (dateTime is null || results.Contains(dateTime.Value))
continue;
results.Add(dateTime.Value);
}
return results;
}
private static List<DateTime> GetDateTimes(DateTime?[] dateTimes, DateTime?[] metadataDateTimes)
{
List<DateTime> results = new();
foreach (DateTime? dateTime in metadataDateTimes)
{
if (dateTime is null || results.Contains(dateTime.Value))
continue;
results.Add(dateTime.Value);
}
foreach (DateTime? dateTime in dateTimes)
{
if (dateTime is null || results.Contains(dateTime.Value))
continue;
results.Add(dateTime.Value);
}
return results;
}
private static List<DateTime> GetDateTimes(FileHolder fileHolder, DateTime?[] dateTimes)
{
List<DateTime> results = new();
string[] digits = Regex.Split(fileHolder.FullName, @"\D+");
foreach (string digit in digits)
{
if (digit.Length != 4 || digit[..2] is not "19" and not "20" || !int.TryParse(digit, out int year))
continue;
results.Add(new(year, 1, 1));
}
foreach (DateTime? dateTime in dateTimes)
{
if (dateTime is null)
continue;
results.Add(dateTime.Value);
}
return results;
}
private static List<DateTime> GetDateTimes(DateTime dateTimeFromName, DateTime?[] dateTimes)
{
List<DateTime> results = new() { dateTimeFromName };
foreach (DateTime? dateTime in dateTimes)
{
if (dateTime is null)
continue;
results.Add(dateTime.Value);
}
return results;
}
#pragma warning disable CA1416
internal static DateTime? GetDateTimeFromName(FileHolder fileHolder)
{
DateTime? result = null;
int length;
string format;
string fullFormat;
StringBuilder value = new();
const string ticksExample = "##################";
string[][] dateFormats = new string[][]
{
new string[] { string.Empty, "yyyyMMdd_HHmmss", string.Empty },
new string[] { string.Empty, "yyyyMMddHHmmssfff", string.Empty },
new string[] { string.Empty, "yyyyMMdd_", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd_", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd.", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd.", $"{ticksExample}.{fileHolder.Length}" },
new string[] { string.Empty, "yyyy-MM-dd HH.mm.ss", string.Empty },
new string[] { string.Empty, "yyyyMMdd_HHmmss", "_LLS" },
new string[] { string.Empty, "yyyyMMdd_HHmmss", "_HDR" },
new string[] { "WIN_", "yyyyMMdd_HH_mm_ss", "_Pro" },
new string[] { "IMG_", "yyyyMMdd_HHmmss", string.Empty },
new string[] { "IMG#####-", "yyyyMMdd-HHmm", string.Empty },
new string[] { "CameraZOOM-", "yyyyMMddHHmmss", string.Empty },
new string[] { "VideoCapture_", "yyyyMMdd-HHmmss ", string.Empty }
};
foreach (string[] dateFormat in dateFormats)
{
_ = value.Clear();
if (dateFormat.Length != 3)
throw new Exception();
fullFormat = string.Join(string.Empty, dateFormat);
if (fileHolder.NameWithoutExtension.Length != fullFormat.Length)
continue;
format = dateFormat[1];
length = dateFormat[0].Length + dateFormat[1].Length;
for (int i = dateFormat[0].Length; i < length; i++)
_ = value.Append(fileHolder.NameWithoutExtension[i]);
if (value.Length != format.Length)
continue;
if (DateTime.TryParseExact(value.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime checkDateTime))
{
if (fileHolder.NameWithoutExtension.Length < ticksExample.Length || !long.TryParse(fileHolder.NameWithoutExtension[^ticksExample.Length..], out long ticks))
result = checkDateTime;
else
result = new DateTime(ticks);
break;
}
}
return result;
}
internal static (string?, DateTime[], Shared.Models.Property) GetProperty(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, Shared.Models.Property? property, bool isIgnoreExtension, bool isValidImageFormatExtension, int? id, ASCIIEncoding asciiEncoding)
{
Shared.Models.Property result;
byte[] bytes;
string value;
long fileLength;
string? message;
int? width = null;
int? height = null;
string? make = null;
string? model = null;
DateTime?[] dateTimes;
string dateTimeFormat;
DateTime checkDateTime;
DateTime? dateTime = null;
PropertyItem? propertyItem;
string? orientation = null;
DateTime? gpsDateStamp = null;
List<DateTime> dateTimesByLogic;
DateTime? dateTimeOriginal = null;
DateTime? dateTimeDigitized = null;
DateTime? dateTimeOriginalByLogic = null;
IReadOnlyList<MetadataExtractor.Directory> directories;
DateTime? dateTimeFromName = GetDateTimeFromName(fileHolder);
if (!isValidImageFormatExtension && fileHolder.Exists && metadata is not null)
{
try
{
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
(dateTimeOriginalByLogic, DateTime?[] metadataDateTimes) = metadata.GetDateTimes(fileHolder, directories);
dateTimesByLogic = GetDateTimes(metadataDateTimes);
message = null;
}
catch (Exception)
{
dateTimesByLogic = new();
message = string.Concat(new StackFrame().GetMethod()?.Name, " <", fileHolder.FullName, ">");
}
}
else if (!isIgnoreExtension && isValidImageFormatExtension && fileHolder.Exists)
{
try
{
using Image image = Image.FromFile(fileHolder.FullName);
width = image.Width;
height = image.Height;
if (populateId && id is null)
{
using Bitmap bitmap = new(image);
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
int length = bitmapData.Stride * bitmap.Height;
bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
id ??= GetDeterministicHashCode(bytes);
}
dateTimeFormat = IProperty.DateTimeFormat();
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTime = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeDigitized = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeOriginal = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
gpsDateStamp = checkDateTime;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Make))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Make);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
make = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Model))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Model);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
model = value;
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.Orientation))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.Orientation);
if (propertyItem?.Value is not null)
{
value = BitConverter.ToInt16(propertyItem.Value, 0).ToString();
orientation = value;
}
}
message = null;
dateTimes = new DateTime?[] { fileHolder.LastWriteTime, fileHolder.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, gpsDateStamp };
}
catch (Exception)
{
dateTimes = Array.Empty<DateTime?>();
message = string.Concat(new StackFrame().GetMethod()?.Name, " <", fileHolder.FullName, ">");
}
if (metadata is not null && dateTimeOriginal is null)
{
try
{
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName);
(dateTimeOriginalByLogic, DateTime?[] metadataDateTimes) = metadata.GetDateTimes(fileHolder, directories);
dateTimesByLogic = GetDateTimes(dateTimes, metadataDateTimes);
message = null;
}
catch (Exception) { message = string.Concat(new StackFrame().GetMethod()?.Name, " <", fileHolder.FullName, ">"); }
}
if (dateTimeFromName is null)
(dateTimeOriginalByLogic, dateTimesByLogic) = (dateTimeOriginal, GetDateTimes(fileHolder, dateTimes));
else
(dateTimeOriginalByLogic, dateTimesByLogic) = (dateTimeOriginal, GetDateTimes(dateTimeFromName.Value, dateTimes));
}
else
(message, dateTimeOriginalByLogic, dateTimesByLogic) = (null, null, new());
if (fileHolder.Length is null)
fileLength = 0;
else
fileLength = fileHolder.Length.Value;
if (fileHolder.CreationTime is null && property?.CreationTime is null)
throw new NullReferenceException(nameof(fileHolder.CreationTime));
if (fileHolder.LastWriteTime is null && property?.LastWriteTime is null)
throw new NullReferenceException(nameof(fileHolder.LastWriteTime));
if (fileHolder.CreationTime is not null && fileHolder.LastWriteTime is not null)
result = new(fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginalByLogic, fileLength, gpsDateStamp, height, id, fileHolder.LastWriteTime.Value, make, model, orientation, width);
else if (property is not null)
result = new(property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginalByLogic, fileLength, gpsDateStamp, height, id, property.LastWriteTime, make, model, orientation, width);
else
throw new NullReferenceException(nameof(property));
return (message, dateTimesByLogic.ToArray(), result);
}
#pragma warning restore CA1416
internal static (DateTime?, DateTime[], int?, string?) Get(bool populateId, IMetadata<MetadataExtractor.Directory>? metadata, FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, ASCIIEncoding asciiEncoding)
{
int? id = null;
string? message;
DateTime[] dateTimes;
Shared.Models.Property? property = null;
if (isIgnoreExtension || !isValidImageFormatExtension)
(message, dateTimes, property) = (null, Array.Empty<DateTime>(), null);
else
(message, dateTimes, property) = GetProperty(populateId, metadata, fileHolder, property, isIgnoreExtension, isValidImageFormatExtension, id, asciiEncoding);
return new(property?.DateTimeOriginal, dateTimes, property?.Id, message);
}
}

View File

@ -3,9 +3,12 @@ using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using ShellProgressBar;
using System.Text;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Rename.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Rename;
@ -18,7 +21,7 @@ public class Rename
List<FileHolder> FileHolders,
bool FfmpegFilesPresent,
DateTime? DateTimeOriginal,
DateTime?[] DateTimes,
DateTime[] DateTimes,
int? Id);
private readonly AppSettings _AppSettings;
@ -85,7 +88,7 @@ public class Rename
if (string.IsNullOrEmpty(directory))
continue;
fileName = Path.GetFileName(file);
if (!fileName.EndsWith(".id"))
if (!fileName.EndsWith(".paddedId"))
continue;
lines = File.ReadAllLines(file);
if (lines.Length < 2)
@ -99,20 +102,23 @@ public class Rename
return results;
}
private List<Record> GetRecords(int offset, ProgressBar progressBar, string[] files)
private List<Record> GetRecords(B_Metadata metadata, int offset, ProgressBar progressBar, string[] files)
{
List<Record> results = new();
int? id;
string? message;
string? directory;
DateTime?[] dateTimes;
DateTime[] dateTimes;
FileHolder fileHolder;
string[]? ffmpegFiles;
bool isIgnoreExtension;
DateTime? dateTimeOriginal;
bool isValidImageFormatExtension;
ASCIIEncoding asciiEncoding = new();
bool nameWithoutExtensionIsIdFormat;
bool nameWithoutExtensionIsPaddedIdFormat;
IReadOnlyList<MetadataExtractor.Directory> directories;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
for (int i = 0; i < files.Length; i++)
{
progressBar.Tick();
@ -122,12 +128,13 @@ public class Rename
directory = Path.GetDirectoryName(files[i]);
if (string.IsNullOrEmpty(directory))
continue;
if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
if (fileHolder.ExtensionLowered == ".paddedId" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
continue;
if (files.Contains($"{fileHolder.FullName}.id"))
if (files.Contains($"{fileHolder.FullName}.paddedId"))
continue;
nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileHolder);
if (nameWithoutExtensionIsIdFormat)
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
if (nameWithoutExtensionIsIdFormat || nameWithoutExtensionIsPaddedIdFormat)
continue;
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
@ -157,7 +164,7 @@ public class Rename
if (fileHolder.DirectoryName is null)
continue;
}
(dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId);
(dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
if (ffmpegFiles is not null)
{
fileHolder = new(files[i]);
@ -171,11 +178,11 @@ public class Rename
return results;
}
private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List<Record> records, int length)
private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List<Record> records, int intMinValueLength)
{
List<(FileHolder, string, string)> results = new();
string id;
int season;
string paddedId;
string checkFile;
bool? isWrongYear;
DateTime dateTime;
@ -189,12 +196,9 @@ public class Rename
string checkFileExtension;
DateTime? dateTimeFromName;
const string jpeg = ".jpeg";
DateTime?[] metadataDateTimes;
List<string> distinct = new();
string[] directoryNameSegments;
DateTime? dateTimeOriginalByLogic;
DateTime? metadataDateTimeOriginal;
IReadOnlyList<MetadataExtractor.Directory> directories;
foreach (Record record in records)
{
progressBar.Tick();
@ -205,19 +209,20 @@ public class Rename
continue;
if (string.IsNullOrEmpty(fileHolder.DirectoryName))
continue;
dateTimeFromName = !record.DateTimes.Any() ? null : record.DateTimes.First();
if (fileHolder.ExtensionLowered == jpeg)
{
if (!record.IsIgnoreExtension && record.IsValidImageFormatExtension)
{
if (File.Exists($"{fileHolder.FullName}.id"))
if (File.Exists($"{fileHolder.FullName}.paddedId"))
{
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.id");
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.paddedId");
if (File.Exists(checkFile))
continue;
if (distinct.Contains(checkFile))
continue;
distinct.Add(checkFile);
results.Add(new(new($"{fileHolder.FullName}.id"), fileHolder.DirectoryName, checkFile));
results.Add(new(new($"{fileHolder.FullName}.paddedId"), fileHolder.DirectoryName, checkFile));
}
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}");
if (File.Exists(checkFile))
@ -238,7 +243,6 @@ public class Rename
continue;
}
}
dateTimeFromName = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder);
minimumDateTime = record.DateTimes.Min();
if (minimumDateTime is null)
throw new NotSupportedException();
@ -246,24 +250,10 @@ public class Rename
timeSpan = null;
else
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - record.DateTimeOriginal.Value.Ticks));
if (timeSpan is not null && timeSpan.Value.TotalMinutes < _AppSettings.MaxMinutesDelta)
(dateTimeOriginalByLogic, metadataDateTimeOriginal, metadataDateTimes) = (record.DateTimeOriginal, null, Array.Empty<DateTime?>());
else
{
if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
continue;
try
{ directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName); }
catch (Exception) { continue; }
(metadataDateTimeOriginal, metadataDateTimes) = Metadata.Models.Stateless.Methods.IMetadata.GetDateTimes(fileHolder, directories);
dateTimeOriginalByLogic = record.DateTimeOriginal is not null ? record.DateTimeOriginal : metadataDateTimeOriginal;
if (record.FfmpegFilesPresent && dateTimeOriginalByLogic is not null)
minimumDateTime = dateTimeOriginalByLogic.Value;
if (dateTimeOriginalByLogic is null)
if (timeSpan is null || timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta)
timeSpan = null;
else
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTimeOriginalByLogic.Value.Ticks));
}
dateTimeOriginalByLogic = record.DateTimeOriginal;
if (timeSpan is null || timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta)
{
if (string.IsNullOrEmpty(_AppSettings.DefaultUnknownDirectoryName))
@ -287,10 +277,8 @@ public class Rename
{
if (dateTimeFromName is not null && isWrongYear is not null && isWrongYear.Value)
minimumDateTime = dateTimeFromName.Value;
else if (dateTimeOriginalByLogic is not null)
minimumDateTime = dateTimeOriginalByLogic.Value;
else
minimumDateTime = new DateTime?[] { record.DateTimes.Where(l => l is not null).Min(), metadataDateTimes.Where(l => l is not null).Min() }.Min();
else if (record.DateTimeOriginal is not null)
minimumDateTime = record.DateTimeOriginal.Value;
if (minimumDateTime is null)
continue;
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
@ -310,9 +298,9 @@ public class Rename
{
if (record.Id is null)
continue;
id = Shared.Models.Stateless.Methods.IDirectory.GetPaddedId(length, record.Index, record.Id.Value);
paddedId = IDirectory.GetPaddedId(intMinValueLength, record.Index, record.Id.Value);
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
checkFile = Path.Combine(seasonDirectory, $"{id}{checkFileExtension}");
checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile == fileHolder.FullName)
continue;
if (File.Exists(checkFile))
@ -359,11 +347,12 @@ public class Rename
const string fileSearchFilter = "*";
const string directorySearchFilter = "*";
List<string> distinctDirectories = new();
B_Metadata metadata = new(_PropertyConfiguration);
List<(FileHolder, string)> verifiedToDoCollection = new();
List<(FileHolder, string, string)> toDoCollection = new();
int offset = Shared.Models.Stateless.Methods.IDirectory.GetOffset();
int offset = IDirectory.GetOffset();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
List<string[]> filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
List<string[]> filesCollection = IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
int count = filesCollection.Select(l => l.Length).Sum();
foreach (string[] files in filesCollection)
{
@ -389,30 +378,29 @@ public class Rename
progressBar = new(files.Length, message, options);
nefPresentCheck = files.Any(l => l.EndsWith(".NEF"));
if (!nefPresentCheck)
records.AddRange(GetRecords(offset + records.Count, progressBar, files));
records.AddRange(GetRecords(metadata, offset + records.Count, progressBar, files));
else
{
if (!nefPresent)
nefPresent = true;
records.AddRange(GetRecords(offset + records.Count, progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray()));
records.AddRange(GetRecords(metadata, offset + records.Count, progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray()));
}
}
progressBar.Dispose();
}
if (records.Any())
{
int length = 0;
int intMinValueLength = int.MinValue.ToString().Length;
foreach (Record record in records)
{
if (record.Id is null)
continue;
if (length > record.Id.Value.ToString().Length)
continue;
length = record.Id.Value.ToString().Length;
if (intMinValueLength < record.Id.Value.ToString().Length)
throw new NotSupportedException();
}
message = $"{length}) comparing records";
message = $"{intMinValueLength}) comparing records";
progressBar = new(records.Count, message, options);
toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records, length));
toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records, intMinValueLength));
progressBar.Dispose();
}
foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection)
@ -431,7 +419,7 @@ public class Rename
if (File.Exists(to))
continue;
verifiedToDoCollection.Add(new(fileHolder, to));
File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}");
File.WriteAllText($"{to}.paddedId", $"{to}{Environment.NewLine}{fileHolder.FullName}");
}
ConsoleKey? consoleKey = null;
log.Information($"Ready to Move {verifiedToDoCollection.Count} files[i](s)?");

View File

@ -70,7 +70,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -94,36 +93,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -294,7 +294,7 @@ public class C_Resize
private void SaveResizedSubfile(Shared.Models.Property property, MappingFromItem mappingFromItem, int[] resize)
{
string dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
string dateTimeFormat = Property.Models.Stateless.IProperty.DateTimeFormat();
DateTime dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
string dateTimeValue = dateTime.ToString(dateTimeFormat);
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);

View File

@ -45,6 +45,7 @@
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>

View File

@ -2,6 +2,8 @@
using Phares.Shared;
using Serilog;
using ShellProgressBar;
using System.Text;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Set.Created.Date.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods;
@ -11,6 +13,8 @@ namespace View_by_Distance.Set.Created.Date;
public class SetCreatedDate
{
private record Record(FileHolder FileHolder, bool OriginalSet, DateTime DateTime);
private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory;
private readonly Configuration _Configuration;
@ -61,19 +65,16 @@ public class SetCreatedDate
{ }
}
private List<(FileHolder, DateTime)> GetToDoCollection(ProgressBar progressBar, List<string[]> filesCollection)
private List<Record> GetRecords(ProgressBar progressBar, ASCIIEncoding asciiEncoding, B_Metadata metadata, string[] files)
{
List<(FileHolder, DateTime)> results = new();
List<Record> results = new();
int? id;
string? message;
DateTime? dateTime;
DateTime[] dateTimes;
FileHolder fileHolder;
DateTime?[] dateTimes;
bool isIgnoreExtension;
DateTime? dateTimeOriginal;
bool isValidImageFormatExtension;
foreach (string[] files in filesCollection)
{
foreach (string file in files)
{
progressBar.Tick();
@ -86,27 +87,54 @@ public class SetCreatedDate
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
if (isIgnoreExtension || !isValidImageFormatExtension)
continue;
(dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId);
dateTime = dateTimeOriginal is not null ? dateTimeOriginal : dateTime = dateTimes.Min();
if (dateTime is null)
(dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
if (dateTimeOriginal is null)
results.Add(new(fileHolder, false, dateTimes.Min()));
else
results.Add(new(fileHolder, true, dateTimeOriginal.Value));
}
return results;
}
private List<Record> GetToDoCollection(ProgressBar progressBar, List<string[]> filesCollection)
{
List<Record> results = new();
int minutes;
Record[] records;
List<Record> unordered;
ASCIIEncoding asciiEncoding = new();
B_Metadata metadata = new(_PropertyConfiguration);
List<Record[]> collections = new();
foreach (string[] files in filesCollection)
{
minutes = 0;
unordered = GetRecords(progressBar, asciiEncoding, metadata, files);
records = (from l in unordered orderby l.DateTime, l.FileHolder.Name.Length, l.FileHolder.Name select l).ToArray();
foreach (Record record in records)
{
if (record.DateTime == record.FileHolder.CreationTime)
continue;
if (dateTime.Value == fileHolder.CreationTime)
continue;
results.Add((fileHolder, dateTime.Value));
if (record.OriginalSet)
results.Add(new(record.FileHolder, record.OriginalSet, record.DateTime));
else
{
minutes += 1;
results.Add(new(record.FileHolder, record.OriginalSet, record.DateTime.AddMinutes(minutes)));
}
}
}
return results;
}
private static List<string> SetCreatedDateForeach(ProgressBar progressBar, List<(FileHolder, DateTime)> toDoCollection)
private static List<string> SetCreatedDateForeach(ProgressBar progressBar, List<Record> toDoCollection)
{
List<string> results = new();
foreach ((FileHolder fileHolder, DateTime dateTime) in toDoCollection)
foreach (Record record in toDoCollection)
{
progressBar.Tick();
results.Add(fileHolder.NameWithoutExtension);
results.Add(record.FileHolder.NameWithoutExtension);
try
{ File.SetCreationTime(fileHolder.FullName, dateTime); }
{ File.SetCreationTime(record.FileHolder.FullName, record.DateTime); }
catch (Exception) { }
}
return results;
@ -124,7 +152,7 @@ public class SetCreatedDate
int count = filesCollection.Select(l => l.Length).Sum();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
progressBar = new(count, message, options);
List<(FileHolder, DateTime)> toDoCollection = GetToDoCollection(progressBar, filesCollection);
List<Record> toDoCollection = GetToDoCollection(progressBar, filesCollection);
progressBar.Dispose();
log.Information($"Ready to set created date {toDoCollection.Count} file(s)?");
for (int y = 0; y < int.MaxValue; y++)

View File

@ -68,7 +68,6 @@
"ResultContent": "()",
"ResultSingleton": "{}",
"RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF",
@ -92,36 +91,6 @@
".TIFF",
".tif",
".TIF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF",
".tif",
".TIF"
]
}
}

View File

@ -0,0 +1,8 @@
namespace View_by_Distance.Shared.Models.Methods;
public interface IMetadata<T>
{
(DateTime?, DateTime?[]) GetDateTimes(FileHolder fileHolder, IReadOnlyList<T> directories);
}

View File

@ -6,6 +6,11 @@ public interface IDirectory
static int GetOffset() =>
1000000;
int TestStatic_GetSortOrderOnlyLengthIndex() =>
GetSortOrderOnlyLengthIndex();
static int GetSortOrderOnlyLengthIndex() =>
GetOffset().ToString().Length + 3;
char TestStatic_GetDirectory(string fileName) =>
GetDirectory(fileName);
static char GetDirectory(string fileName) =>
@ -16,10 +21,23 @@ public interface IDirectory
static int GetDirectory(char directory) =>
directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11;
string TestStatic_GetPaddedId(int length, int index, int id) =>
GetPaddedId(length, index, id);
static string GetPaddedId(int length, int index, int id) =>
id > -1 ? $"{index}070{id.ToString().PadLeft(length, '0')}" : $"{index}030{id.ToString()[1..].PadLeft(length, '0')}";
string TestStatic_GetPaddedId(int intMinValueLength, int index, int id) =>
GetPaddedId(intMinValueLength, index, id);
static string GetPaddedId(int intMinValueLength, int index, int id) =>
id > -1 ? $"{index}070{id.ToString().PadLeft(intMinValueLength, '0')}" : $"{index}030{id.ToString()[1..].PadLeft(intMinValueLength, '0')}";
bool TestStatic_NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, int sortOrderOnlyLengthIndex) =>
NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
static bool NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, int sortOrderOnlyLengthIndex) =>
fileNameWithoutExtension.Length > sortOrderOnlyLengthIndex
&& fileNameWithoutExtension[sortOrderOnlyLengthIndex] == '0'
&& fileNameWithoutExtension[sortOrderOnlyLengthIndex - 3] == '0'
&& fileNameWithoutExtension.All(l => char.IsNumber(l));
bool TestStatic_NameWithoutExtensionIsPaddedIdFormat(Models.FileHolder fileHolder, int sortOrderOnlyLengthIndex) =>
NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
static bool NameWithoutExtensionIsPaddedIdFormat(Models.FileHolder fileHolder, int sortOrderOnlyLengthIndex) =>
NameWithoutExtensionIsPaddedIdFormat(fileHolder.NameWithoutExtension, sortOrderOnlyLengthIndex);
List<string[]> TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter) =>
GetFilesCollection(directory, directorySearchFilter, fileSearchFilter);
@ -51,6 +69,11 @@ public interface IDirectory
static void MoveFiles(List<string> files, string find, string replace) =>
XDirectory.MoveFiles(files, find, replace);
(string[], List<(Models.FileHolder, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, List<string[]> filesCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, filesCollection, directories, tick);
static (string[], List<(Models.FileHolder, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, List<string[]> filesCollection, string[] directories, Action? tick) =>
XDirectory.GetToDoCollection(propertyConfiguration, copyDuplicates: false, ifCanUseId: true, filesCollection, directories, tick);
(string[], List<(Models.FileHolder, string)>) TestStatic_GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, List<string[]> filesCollection, string[] directories, Action? tick) =>
GetToDoCollection(propertyConfiguration, copyDuplicates, ifCanUseId, filesCollection, directories, tick);
static (string[], List<(Models.FileHolder, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, List<string[]> filesCollection, string[] directories, Action? tick) =>

View File

@ -1,24 +1,8 @@
using System.Drawing.Imaging;
using System.Reflection;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IProperty
{ // ...
string TestStatic_DateTimeFormat();
static string DateTimeFormat() => "yyyy:MM:dd HH:mm:ss";
int TestStatic_GetDeterministicHashCode(byte[] value) =>
GetDeterministicHashCode(value);
static int GetDeterministicHashCode(byte[] value) =>
Property.GetDeterministicHashCode(value);
DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
GetDateTime(dateTimeFormat, value);
static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
Property.GetDateTime(dateTimeFormat, value);
DateTime TestStatic_GetDateTime(Models.Property? property) =>
GetDateTime(property);
static DateTime GetDateTime(Models.Property? property) =>
@ -54,26 +38,11 @@ public interface IProperty
static (bool?, string[]) IsWrongYear(Models.FileHolder fileHolder, DateTime? dateTimeOriginal, List<DateTime> dateTimes) =>
Property.IsWrongYear(fileHolder, dateTimeOriginal, dateTimes);
(DateTime?, DateTime?[], int?, string?) TestStatic_Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId) =>
Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, populateId);
static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId) =>
Property.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, populateId);
DateTime? TestStatic_GetDateTimeFromName(Models.FileHolder fileHolder) =>
GetDateTimeFromName(fileHolder);
static DateTime? GetDateTimeFromName(Models.FileHolder fileHolder) =>
Property.GetDateTimeFromName(fileHolder);
bool TestStatic_NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
Property.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
bool TestStatic_NameWithoutExtensionIsIdFormat(string[] validImageFormatExtensions, Models.FileHolder fileHolder) =>
NameWithoutExtensionIsIdFormat(validImageFormatExtensions, fileHolder);
static bool NameWithoutExtensionIsIdFormat(string[] validImageFormatExtensions, Models.FileHolder fileHolder) =>
Property.NameWithoutExtensionIsIdFormat(validImageFormatExtensions, fileHolder);
bool TestStatic_NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) =>
NameWithoutExtensionIsIdFormat(fileHolder);
static bool NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) =>
@ -104,14 +73,4 @@ public interface IProperty
static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp) =>
Property.GetDateTimes(creationTime, lastWriteTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, gpsDateStamp);
byte[] TestStatic_GetBytes(string value) =>
GetBytes(value);
static byte[] GetBytes(string value) =>
Property.GetBytes(value);
PropertyItem TestStatic_GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
GetPropertyItem(constructorInfo, id, type, value);
static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value) =>
Property.GetPropertyItem(constructorInfo, id, type, value);
}

View File

@ -1,11 +1,3 @@
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Property
@ -24,25 +16,6 @@ internal abstract class Property
return result;
}
internal static int GetDeterministicHashCode(byte[] value)
{
int result;
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
result = hash1 + (hash2 * 1566083941);
}
return result;
}
internal static (bool?, string[]) IsWrongYear(string[] segments, string year)
{
bool? result;
@ -113,57 +86,6 @@ internal abstract class Property
return new(result, results);
}
internal static DateTime? GetDateTimeFromName(Models.FileHolder fileHolder)
{
DateTime? result = null;
int length;
string format;
string fullFormat;
StringBuilder value = new();
const string ticksExample = "##################";
string[][] dateFormats = new string[][]
{
new string[] { string.Empty, "yyyyMMdd_HHmmss", string.Empty },
new string[] { string.Empty, "yyyyMMddHHmmssfff", string.Empty },
new string[] { string.Empty, "yyyyMMdd_", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd_", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd.", ticksExample },
new string[] { string.Empty, "yyyy-MM-dd.", $"{ticksExample}.{fileHolder.Length}" },
new string[] { string.Empty, "yyyy-MM-dd HH.mm.ss", string.Empty },
new string[] { string.Empty, "yyyyMMdd_HHmmss", "_LLS" },
new string[] { string.Empty, "yyyyMMdd_HHmmss", "_HDR" },
new string[] { "WIN_", "yyyyMMdd_HH_mm_ss", "_Pro" },
new string[] { "IMG_", "yyyyMMdd_HHmmss", string.Empty },
new string[] { "IMG#####-", "yyyyMMdd-HHmm", string.Empty },
new string[] { "CameraZOOM-", "yyyyMMddHHmmss", string.Empty },
new string[] { "VideoCapture_", "yyyyMMdd-HHmmss ", string.Empty }
};
foreach (string[] dateFormat in dateFormats)
{
_ = value.Clear();
if (dateFormat.Length != 3)
throw new Exception();
fullFormat = string.Join(string.Empty, dateFormat);
if (fileHolder.NameWithoutExtension.Length != fullFormat.Length)
continue;
format = dateFormat[1];
length = dateFormat[0].Length + dateFormat[1].Length;
for (int i = dateFormat[0].Length; i < length; i++)
_ = value.Append(fileHolder.NameWithoutExtension[i]);
if (value.Length != format.Length)
continue;
if (DateTime.TryParseExact(value.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime checkDateTime))
{
if (fileHolder.NameWithoutExtension.Length < ticksExample.Length || !long.TryParse(fileHolder.NameWithoutExtension[^ticksExample.Length..], out long ticks))
result = checkDateTime;
else
result = new DateTime(ticks);
break;
}
}
return result;
}
internal static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp)
{
List<DateTime> results = new()
@ -355,7 +277,8 @@ internal abstract class Property
internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension)
{
bool result;
if (fileNameWithoutExtension.Length < 5)
int intMinValueLength = int.MinValue.ToString().Length;
if (fileNameWithoutExtension.Length < 5 || fileNameWithoutExtension.Length > intMinValueLength)
result = false;
else
{
@ -365,181 +288,4 @@ internal abstract class Property
return result;
}
internal static bool NameWithoutExtensionIsIdFormat(string[] validImageFormatExtensions, Models.FileHolder fileHolder)
{
bool result;
bool changed;
string? fileNameWithoutExtension = fileHolder.NameWithoutExtension;
for (int i = 0; i < validImageFormatExtensions.Length; i++)
{
changed = false;
foreach (string validImageFormatExtension in validImageFormatExtensions)
{
if (fileNameWithoutExtension.EndsWith(validImageFormatExtension))
{
changed = true;
fileNameWithoutExtension = fileNameWithoutExtension[..^validImageFormatExtension.Length];
break;
}
}
if (!changed)
break;
}
result = NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
return result;
}
#pragma warning disable CA1416
internal static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId)
{
int? id = null;
string? message = null;
DateTime? dateTime = null;
DateTime? gpsDateStamp = null;
DateTime? dateTimeOriginal = null;
DateTime? dateTimeDigitized = null;
if (!isIgnoreExtension && isValidImageFormatExtension)
{
try
{
byte[] bytes;
string value;
DateTime checkDateTime;
PropertyItem? propertyItem;
ASCIIEncoding asciiEncoding = new();
string dateTimeFormat = IProperty.DateTimeFormat();
using Image image = Image.FromFile(fileHolder.FullName);
if (!populateId)
id = null;
else
{
using Bitmap bitmap = new(image);
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
int length = bitmapData.Stride * bitmap.Height;
bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
id = IProperty.GetDeterministicHashCode(bytes);
bitmap.Dispose();
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTime = checkDateTime;
else
dateTime = GetDateTime(dateTimeFormat, value);
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeDigitized))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeDigitized);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeDigitized = checkDateTime;
else
dateTimeDigitized = GetDateTime(dateTimeFormat, value);
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.DateTimeOriginal))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTimeOriginal);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
dateTimeOriginal = checkDateTime;
else
dateTimeOriginal = GetDateTime(dateTimeFormat, value);
}
}
if (image.PropertyIdList.Contains((int)IExif.Tags.GPSDateStamp))
{
propertyItem = image.GetPropertyItem((int)IExif.Tags.GPSDateStamp);
if (propertyItem?.Value is not null)
{
value = asciiEncoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
if (value.Length > dateTimeFormat.Length)
value = value[..dateTimeFormat.Length];
if (value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out checkDateTime))
gpsDateStamp = checkDateTime;
else
gpsDateStamp = GetDateTime(dateTimeFormat, value);
}
}
image.Dispose();
}
}
catch (Exception)
{
message = string.Concat(new StackFrame().GetMethod()?.Name, " <", fileHolder.FullName, ">");
}
}
DateTime?[] dateTimes = new DateTime?[] { fileHolder.LastWriteTime, fileHolder.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, gpsDateStamp };
return new(dateTimeOriginal, dateTimes, id, message);
}
internal static PropertyItem GetPropertyItem(ConstructorInfo constructorInfo, int id, short type, string value)
{
PropertyItem result = (PropertyItem)constructorInfo.Invoke(null);
int length;
byte[] bytes;
if (type == 2)
{
bytes = GetBytes(value);
length = value.Length + 1;
}
else if (type == 1)
{
bytes = Encoding.Unicode.GetBytes($"{value}\0");
length = bytes.Length;
}
else
throw new NotSupportedException();
result.Id = id;
result.Len = length;
result.Type = type;
result.Value = bytes;
return result;
}
#pragma warning restore CA1416
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
{
DateTime? result;
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
result = dateTime;
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
result = dateTime;
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
result = dateTime;
else
result = null;
return result;
}
internal static byte[] GetBytes(string value)
{
byte[] results = new byte[value.Length + 1];
for (int i = 0; i < value.Length; i++)
results[i] = (byte)value[i];
results[value.Length] = 0x00;
return results;
}
}

View File

@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract partial class XDirectory
{
private record SortedRecord(int? Id, Models.FileHolder FileHolder);
private record SortedRecord(Models.FileHolder FileHolder, bool NameWithoutExtensionIsIdFormat, int? Id);
private static int GetCeilingAverage(List<string[]> fileCollection)
{
@ -244,7 +244,7 @@ internal abstract partial class XDirectory
else if (fromFileInfo.Length == toFileInfo.Length && fromFileInfo.LastWriteTime == toFileInfo.LastWriteTime)
checkDirectory = string.Concat(checkDirectory, ".del");
else
checkDirectory = string.Concat(checkDirectory, ".i");
checkDirectory = string.Concat(checkDirectory, ".j");
}
File.Move(from, checkDirectory);
}
@ -280,30 +280,35 @@ internal abstract partial class XDirectory
}
}
private static (bool, SortedRecord[]) GetSortedRecords(List<string[]> filesCollection)
private static SortedRecord[] GetSortedRecords(List<string[]> filesCollection)
{
bool result = true;
List<SortedRecord> results = new();
int? id;
short? multiplier;
char negativeMarker;
int absoluteValueOfId;
Models.FileHolder fileHolder;
int offset = IDirectory.GetOffset();
int offsetLength = offset.ToString().Length;
int sortOrderOnlyLengthIndex = offsetLength + 3;
bool nameWithoutExtensionIsIdFormat;
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
foreach (string[] files in filesCollection)
{
foreach (string file in files)
{
fileHolder = new Models.FileHolder(file);
if (!result)
nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileHolder);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
if (nameWithoutExtensionIsIdFormat)
{
multiplier = null;
if (!int.TryParse(fileHolder.NameWithoutExtension, out absoluteValueOfId))
id = null;
else
id = absoluteValueOfId;
}
else if (!nameWithoutExtensionIsPaddedIdFormat)
{
if (fileHolder.NameWithoutExtension.Length < sortOrderOnlyLengthIndex)
{
result = false;
id = null;
multiplier = null;
}
else
@ -314,45 +319,52 @@ internal abstract partial class XDirectory
else if (negativeMarker == '3')
multiplier = -1;
else
{
result = false;
multiplier = null;
}
}
}
if (!result)
id = null;
else if (!int.TryParse(fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId))
if (!int.TryParse(fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId))
id = null;
else
{
id = absoluteValueOfId * multiplier;
results.Add(new(id, fileHolder));
if (id is null || !fileHolder.NameWithoutExtension.EndsWith(id.Value.ToString()[1..]))
id = null;
}
}
return new(result, (from l in results orderby l.FileHolder.LastWriteTime, l.FileHolder.FullName.Length descending select l).ToArray());
results.Add(new(fileHolder, nameWithoutExtensionIsIdFormat, id));
}
}
return (from l in results orderby l.FileHolder.CreationTime, l.FileHolder.FullName.Length descending select l).ToArray();
}
internal static (string[], List<(Models.FileHolder, string)>) GetToDoCollection(Properties.IPropertyConfiguration propertyConfiguration, bool copyDuplicates, bool ifCanUseId, List<string[]> filesCollection, string[] directories, Action? tick)
{
List<(Models.FileHolder, string)> results = new();
string paddedId;
string checkFile;
string directory;
FileInfo fileInfo;
int directoryIndex;
string directoryName;
string paddedIdFile;
bool wrapped = false;
string directoryName;
bool paddedCheck = false;
SortedRecord sortedRecord;
Models.FileHolder fileHolder;
List<int> distinctIds = new();
List<string> distinct = new();
int offset = IDirectory.GetOffset();
List<string> distinctDirectories = new();
(bool all, SortedRecord[] sortedRecords) = GetSortedRecords(filesCollection);
foreach (SortedRecord sortedRecord in sortedRecords)
int intMinValueLength = int.MinValue.ToString().Length;
SortedRecord[] sortedRecords = GetSortedRecords(filesCollection);
for (int i = 0; i < sortedRecords.Length; i++)
{
tick?.Invoke();
if (sortedRecord.FileHolder.Name.EndsWith("len") || sortedRecord.FileHolder.ExtensionLowered == ".id" || sortedRecord.FileHolder.ExtensionLowered == ".lsv" || sortedRecord.FileHolder.DirectoryName is null)
sortedRecord = sortedRecords[i];
fileHolder = sortedRecord.FileHolder;
if (fileHolder.Name.EndsWith("len") || fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
continue;
(_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, sortedRecord.FileHolder.NameWithoutExtension);
directoryName = Path.GetFileName(sortedRecord.FileHolder.DirectoryName);
if (directoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !sortedRecord.FileHolder.Name.StartsWith(directoryName))
(_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, fileHolder.NameWithoutExtension);
directoryName = Path.GetFileName(fileHolder.DirectoryName);
if (directoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !fileHolder.Name.StartsWith(directoryName))
{
if (wrapped)
continue;
@ -364,28 +376,35 @@ internal abstract partial class XDirectory
wrapped = true;
directory = Path.Combine(directories[directoryIndex], directoryName);
}
if (all)
if (ifCanUseId && sortedRecord.NameWithoutExtensionIsIdFormat && sortedRecord.Id is not null && fileHolder.DirectoryName is not null)
{
if (sortedRecord.Id is null || !sortedRecord.FileHolder.NameWithoutExtension.EndsWith(sortedRecord.Id.Value.ToString()[1..]))
throw new NotSupportedException();
paddedId = IDirectory.GetPaddedId(intMinValueLength, offset + i, sortedRecord.Id.Value);
paddedIdFile = Path.Combine(fileHolder.DirectoryName, $"{paddedId}{fileHolder.ExtensionLowered}");
if (!File.Exists(paddedIdFile))
{
File.Move(fileHolder.FullName, paddedIdFile);
fileHolder = new(paddedIdFile);
if (!paddedCheck)
paddedCheck = true;
}
if (all && ifCanUseId)
checkFile = Path.Combine(directory, $"{sortedRecord.Id}{sortedRecord.FileHolder.ExtensionLowered}");
}
if (ifCanUseId)
checkFile = Path.Combine(directory, $"{sortedRecord.Id}{fileHolder.ExtensionLowered}");
else
checkFile = Path.Combine(directory, $"{sortedRecord.FileHolder.NameWithoutExtension}{sortedRecord.FileHolder.ExtensionLowered}");
checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}{fileHolder.ExtensionLowered}");
if ((sortedRecord.Id is not null && distinctIds.Contains(sortedRecord.Id.Value)) || distinct.Contains(checkFile))
{
if (string.IsNullOrEmpty(sortedRecord.FileHolder.DirectoryName))
if (string.IsNullOrEmpty(fileHolder.DirectoryName))
continue;
if (!copyDuplicates)
continue;
for (int i = 1; i < int.MaxValue; i++)
for (int j = 1; j < int.MaxValue; j++)
{
fileInfo = new(checkFile);
if (!fileInfo.Exists || sortedRecord.FileHolder.Length == fileInfo.Length && sortedRecord.FileHolder.LastWriteTime == fileInfo.LastWriteTime)
checkFile = Path.Combine(directory, $"{sortedRecord.FileHolder.NameWithoutExtension}.{i}dup{sortedRecord.FileHolder.ExtensionLowered}");
if (!fileInfo.Exists || fileHolder.Length == fileInfo.Length && fileHolder.LastWriteTime == fileInfo.LastWriteTime)
checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}.{j}dup{fileHolder.ExtensionLowered}");
else
checkFile = Path.Combine(directory, $"{sortedRecord.FileHolder.NameWithoutExtension}.{i}why{sortedRecord.FileHolder.ExtensionLowered}");
checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}.{j}why{fileHolder.ExtensionLowered}");
if (sortedRecord.Id is not null)
{
if (distinctIds.Contains(sortedRecord.Id.Value))
@ -395,7 +414,7 @@ internal abstract partial class XDirectory
if (distinct.Contains(checkFile))
continue;
distinct.Add(checkFile);
results.Add(new(sortedRecord.FileHolder, checkFile));
results.Add(new(fileHolder, checkFile));
if (!distinctDirectories.Contains(directory))
distinctDirectories.Add(directory);
break;
@ -405,10 +424,12 @@ internal abstract partial class XDirectory
distinct.Add(checkFile);
if (sortedRecord.Id is not null)
distinctIds.Add(sortedRecord.Id.Value);
results.Add(new(sortedRecord.FileHolder, checkFile));
results.Add(new(fileHolder, checkFile));
if (!distinctDirectories.Contains(directory))
distinctDirectories.Add(directory);
}
if (paddedCheck)
throw new Exception("Maybe need to restart application!");
return (distinctDirectories.ToArray(), results);
}

View File

@ -143,6 +143,7 @@ public class UnitTestResize
List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection;
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = new string[] { nameof(A_Property) };
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(l => char.IsNumber(l));
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
@ -170,7 +171,7 @@ public class UnitTestResize
Assert.IsNotNull(item.ImageFileHolder);
if (item.Property is null)
{
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
}
if (property is null || item.Property is null)
@ -180,7 +181,7 @@ public class UnitTestResize
_ = blurHasher.Encode(resizedFileHolder);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
(int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem);
(int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, 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, outputResolutionToResize);

View File

@ -217,6 +217,7 @@ public class UnitTestFace
List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection;
int length = _PropertyConfiguration.RootDirectory.Length;
string[] changesFrom = new string[] { nameof(A_Property) };
string outputResolution = _Configuration.OutputResolutions[0];
bool outputResolutionHasNumber = outputResolution.Any(l => char.IsNumber(l));
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
@ -244,7 +245,7 @@ public class UnitTestFace
Assert.IsNotNull(item.ImageFileHolder);
if (item.Property is null)
{
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property);
}
if (property is null || item.Property is null)
@ -252,7 +253,7 @@ public class UnitTestFace
resizedFileHolder = resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
item.SetResizedFileHolder(resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(item);
(int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem);
(int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, 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, outputResolutionToResize);