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) - [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) - [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) - [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 ## 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 ## Done
@ -45,3 +42,6 @@ taskTemplate: '^+^_${overdue ? ''^R'' : ''''}${name}^: ${relations ? (''\n^-^/^g
- [run-scan-originals](tasks/run-scan-originals.md) - [run-scan-originals](tasks/run-scan-originals.md)
- [shrink-percent](tasks/shrink-percent.md) - [shrink-percent](tasks/shrink-percent.md)
- [setup-photo-prism-again-in-wsl-docker](tasks/setup-photo-prism-again-in-wsl-docker.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 created: 2023-06-18T20:29:10.288Z
updated: 2023-07-08T21:21:04.820Z updated: 2023-07-09T23:00:08.674Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []
status: "3-In Progress" status: '3-In Progress'
type: kanbn type: kanbn
--- ---

View File

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

View File

@ -1,10 +1,10 @@
--- ---
created: 2023-06-24T02:13:16.426Z created: 2023-06-24T02:13:16.426Z
updated: 2023-07-08T21:21:06.222Z updated: 2023-07-09T23:00:05.524Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []
status: "3-In Progress" status: '3-In Progress'
type: kanbn type: kanbn
--- ---
@ -15,4 +15,4 @@ type: kanbn
- [x] Convert to .tiff with Nikon Nx Studio - [x] Convert to .tiff with Nikon Nx Studio
- [x] Keep .nef files in 2-Images-B - [x] Keep .nef files in 2-Images-B
- [x] Convert .tiff to .jpg with Nikon Nx Studio at 100% - [x] Convert .tiff to .jpg with Nikon Nx Studio at 100%
- [x] Use Rename console app to rename for storage - [x] Use Rename console app to rename for storage

View File

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

View File

@ -1,17 +1,22 @@
--- ---
created: 2023-07-08T21:25:25.925Z created: 2023-07-08T21:25:25.925Z
updated: 2023-07-08T21:45:42.263Z updated: 2023-07-10T05:03:00.856Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []
started: 2023-07-08T21:45:42.263Z started: 2023-07-08T21:45:42.263Z
type: note
--- ---
# Rename files to padded number string # Rename Files to Padded Number String
## Sub-tasks ## Sub-tasks
- [ ] ~~Go Back to Index for Sort~~ - [ ] ~~Go Back to Index for Sort~~
- [ ] New file for index to to id - [ ] ~~New file for index to to id~~
- [ ] Count backwards - [ ] ~~Count backwards~~
- [ ] Maybe skip some for scan images - [ ] ~~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 created: 2023-07-05T22:17:38.271Z
updated: 2023-07-08T21:47:12.461Z updated: 2023-07-10T00:16:19.096Z
status: 2-Todo status: 2-Todo
type: kanbn type: kanbn
started: 2023-07-08T21:47:12.461Z started: 2023-07-08T21:47:12.461Z
@ -8,6 +8,15 @@ started: 2023-07-08T21:47:12.461Z
# Set Date Taken When Missing # 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 ## 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 created: 2023-06-23T13:56:11.956Z
updated: 2023-07-08T21:21:06.224Z updated: 2023-07-09T23:00:03.100Z
assigned: "" assigned: ""
progress: 0 progress: 0
tags: [] tags: []
status: "3-In Progress" status: '3-In Progress'
type: kanbn type: kanbn
--- ---

View File

@ -88,7 +88,6 @@
"PopulatePropertyId": true, "PopulatePropertyId": true,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -120,36 +119,6 @@
".tif", ".tif",
".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": [ "VerifyToSeason": [
". 2000", ". 2000",
". 2001", ". 2001",

View File

@ -122,34 +122,6 @@
".tif", ".tif",
".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": [ "VerifyToSeason": [
". 2000", ". 2000",
". 2001", ". 2001",

View File

@ -24,4 +24,4 @@ public record AppSettings(string Company,
[JsonSerializable(typeof(AppSettings))] [JsonSerializable(typeof(AppSettings))]
internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

@ -66,4 +66,4 @@ public class AppSettings
[JsonSerializable(typeof(AppSettings))] [JsonSerializable(typeof(AppSettings))]
internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

@ -70,7 +70,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -94,36 +93,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

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

View File

@ -69,7 +69,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/phares/Pictures", "RootDirectory": "C:/Tmp/phares/Pictures",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -95,36 +94,6 @@
".tif", ".tif",
".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": [ "VerifyToSeason": [
". 2000", ". 2000",
". 2001", ". 2001",

View File

@ -71,7 +71,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -95,36 +94,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -90,36 +89,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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" /> <PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup> </ItemGroup>

View File

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

View File

@ -50,5 +50,48 @@
"ValidKeyWords": [ "ValidKeyWords": [
"Review" "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": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -92,36 +91,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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)) using (graphics = Graphics.FromImage(bitmap))
graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel); 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); 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); 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.SetPropertyItem(propertyItem);
bitmap.Save(fileInfo.FullName, _ImageCodecInfo, _EncoderParameters); 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.Resize.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Stateless.Methods;
using WindowsShortcutFactory; using WindowsShortcutFactory;
namespace View_by_Distance.Instance; 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 peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception(); string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception();
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
(_GenealogicalDataCommunicationHeaderLines, Dictionary<string, List<string>> individuals, _GenealogicalDataCommunicationFooterLines) = Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true); (_GenealogicalDataCommunicationHeaderLines, Dictionary<string, List<string>> individuals, _GenealogicalDataCommunicationFooterLines) = IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true);
_PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); _PersonContainers = IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals);
VerifyPersonContainersDisplayDirectoryAllFiles(); VerifyPersonContainersDisplayDirectoryAllFiles();
} }
{ {
@ -321,9 +322,9 @@ public partial class DlibDotNet
eyeα = α is null ? null : (int)Math.Round(Math.Abs(α.Value)); eyeα = α is null ? null : (int)Math.Round(Math.Abs(α.Value));
} }
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence); 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); 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); mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection); mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
@ -356,7 +357,7 @@ public partial class DlibDotNet
else else
{ {
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits); 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); mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation); inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection); mappingFromFilter = new(isFocusModel, isFocusRelativePath, isIgnoreRelativePath, inSkipCollection);
@ -413,12 +414,13 @@ public partial class DlibDotNet
List<string> parseExceptions = new(); List<string> parseExceptions = new();
List<Tuple<string, DateTime>> subFileTuples = new(); List<Tuple<string, DateTime>> subFileTuples = new();
List<KeyValuePair<string, string>> metadataCollection; List<KeyValuePair<string, string>> metadataCollection;
string[] changesFrom = new string[] { nameof(A_Property) };
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber); FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
if (item.Property is null || item.Property.Id is null || item.Any()) if (item.Property is null || item.Property.Id is null || item.Any())
{ {
LogItemPropertyIsNull(item); LogItemPropertyIsNull(item);
int? propertyHashCode = item.Property?.GetHashCode(); int? propertyHashCode = item.Property?.GetHashCode();
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions); property = propertyLogic.GetProperty(metadata, item, subFileTuples, parseExceptions);
item.Update(property); item.Update(property);
if (propertyHashCode is null) 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)); subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), item.SourceDirectoryFileHolder.LastWriteTime.Value));
else else
subFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), new FileInfo(item.SourceDirectoryFileHolder.FullName).LastWriteTime)); 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 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()) if (nameWithoutExtensionIsIdFormat && item.ImageFileHolder.NameWithoutExtension != item.Property.Id.ToString())
LogNameWithoutExtensionIsIdFormatBut(item); 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)) 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); string? file = _BlurHasher.GetFile(resizedFileHolder);
@ -451,8 +457,8 @@ public partial class DlibDotNet
if (property is null || item.Property is null) if (property is null || item.Property is null)
throw new NullReferenceException(nameof(property)); throw new NullReferenceException(nameof(property));
item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder); item.SetResizedFileHolder(_Resize.FileNameExtension, resizedFileHolder);
MappingFromItem mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder); MappingFromItem mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
(int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, mappingFromItem); (int metadataGroups, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, changesFrom, mappingFromItem);
if (_AppSettings.MaxDegreeOfParallelism < 2) if (_AppSettings.MaxDegreeOfParallelism < 2)
ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection)); ticks = LogDelta(ticks, nameof(B_Metadata.GetMetadataCollection));
Dictionary<string, int[]> outputResolutionToResize = _Resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem); 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) 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 dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, "()"); string d2FacePartsContentDirectory = Path.Combine(d2ResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
string d2FacePartsContentCollectionDirectory = Path.Combine(d2ResultsFullGroupDirectory, "[()]"); 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()) if (distinctFilteredMappingCollection.Any())
{ {
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(d2FacePartsContentDirectory, ticks); 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) private static void LookForAbandoned(List<int> distinctFilteredIds, string directory, string directoryName)
{ {
string fileNameWithoutExtension; string fileNameWithoutExtension;
bool nameWithoutExtensionIsIdFormat;
List<string> renameCollection = new(); List<string> renameCollection = new();
bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray(); string[] distinctFilteredIdsValues = distinctFilteredIds.Select(l => l.ToString()).ToArray();
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories); string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files) foreach (string file in files)
{ {
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file))); 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; continue;
if (!Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension)) if (distinctFilteredIdsValues.Contains(fileNameWithoutExtension))
continue; continue;
renameCollection.Add(file); renameCollection.Add(file);
} }
if (renameCollection.Any()) if (renameCollection.Any())
{ {
if (directoryName.Length == 2) 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) 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 else
throw new NotSupportedException(); 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(); List<string> renameCollection = new();
foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in idToLocationContainers) foreach (KeyValuePair<int, List<LocationContainer<MetadataExtractor.Directory>>> keyValuePair in idToLocationContainers)
@ -921,7 +932,7 @@ public partial class DlibDotNet
} }
} }
if (renameCollection.Any()) 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) 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) if (item.Property?.Id is null || item.ResizedFileHolder is null)
continue; continue;
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder); mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, item.ResizedFileHolder);
if (distinctItems) if (distinctItems)
{ {
if (distinct.Contains(item.Property.Id.Value)) if (distinct.Contains(item.Property.Id.Value))
@ -1137,6 +1148,7 @@ public partial class DlibDotNet
private void Search(long ticks, string argZero, string propertyRoot) private void Search(long ticks, string argZero, string propertyRoot)
{ {
int t; int t;
int count;
string message; string message;
Container[] containers; Container[] containers;
A_Property propertyLogic; A_Property propertyLogic;
@ -1151,26 +1163,53 @@ public partial class DlibDotNet
string fPhotoPrismContentDirectory; string fPhotoPrismContentDirectory;
const string fileSearchFilter = "*"; const string fileSearchFilter = "*";
string fPhotoPrismSingletonDirectory; string fPhotoPrismSingletonDirectory;
bool filesCollectionCountIsOne = false;
List<string[]>? filesCollection = null;
const string directorySearchFilter = "*"; const string directorySearchFilter = "*";
Dictionary<long, List<int>> personKeyToIds; Dictionary<long, List<int>> personKeyToIds;
bool eLastWriteTimeTimeSpanIsMoreThen = false;
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection; Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection;
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); TimeSpan eLastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(eDistanceContentDirectory).LastWriteTime.Ticks);
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); foreach (string outputResolution in _Configuration.OutputResolutions)
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)
{ {
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; string resultsGroupDirectory;
a2PeopleContentDirectory = null; a2PeopleContentDirectory = null;
eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()"); eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()"); fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultContent);
fPhotoPrismSingletonDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "{}"); fPhotoPrismSingletonDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", _Configuration.PropertyConfiguration.ResultSingleton);
for (int i = 1; i < 10; i++) for (int i = 1; i < 10; i++)
{ {
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); 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); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); 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))) foreach (string outputResolution in _Configuration.OutputResolutions)
continue; {
if (eLastWriteTimeTimeSpan.TotalDays < 1) if (outputResolution.Any(l => char.IsNumber(l)))
continue;
(cResultsFullGroupDirectory, _, _, _) = GetResultsFullGroupDirectories(outputResolution);
filesCollection = IDirectory.GetFilesCollection(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent, _Configuration.PropertyConfiguration.ResultAllInOne), directorySearchFilter, fileSearchFilter);
count = filesCollection.Select(l => l.Length).Sum();
break; 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();
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)"; message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
using (ProgressBar progressBar = new(2, message, options)) using (ProgressBar progressBar = new(2, message, options))
{ {
progressBar.Tick(); progressBar.Tick();
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}"); string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton);
if (!Directory.Exists(aPropertySingletonDirectory)) if (!Directory.Exists(aPropertySingletonDirectory))
_ = Directory.CreateDirectory(aPropertySingletonDirectory); _ = Directory.CreateDirectory(aPropertySingletonDirectory);
(t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollection); (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); fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, new(_PersonContainers), ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); 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); containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
personKeyToIds = mapLogic.GetPersonKeyToIds(); personKeyToIds = mapLogic.GetPersonKeyToIds();
if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && !string.IsNullOrEmpty(a2PeopleContentDirectory) && _GenealogicalDataCommunicationHeaderLines is not null && _GenealogicalDataCommunicationFooterLines is not null && _GenealogicalDataCommunicationHeaderLines.Any() && _GenealogicalDataCommunicationFooterLines.Any()) 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(); ReadOnlyDictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers = mapLogic.GetIdToLocationContainers();
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, idToLocationContainers, mapLogic); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, idToLocationContainers, mapLogic);
if (_Configuration.LookForAbandoned) if (_Configuration.LookForAbandoned)
@ -1257,11 +1290,11 @@ public partial class DlibDotNet
continue; continue;
if (!_IsEnvironment.Development) if (!_IsEnvironment.Development)
{ {
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(aResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(bResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultSingleton));
if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) 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; 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() public override string ToString()
{ {
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings);
return result; return result;
} }
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AppSettings))]
internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext
{
} }

View File

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

View File

@ -121,7 +121,6 @@
"SortingMinimumToUseSigma": 10, "SortingMinimumToUseSigma": 10,
"TestDistanceResults": true, "TestDistanceResults": true,
"UseFilterTries": 0, "UseFilterTries": 0,
"WriteBitmapDataBytes": false,
"CopyFacesAndSaveFaceLandmarkForOutputResolutions": [], "CopyFacesAndSaveFaceLandmarkForOutputResolutions": [],
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
@ -187,36 +186,6 @@
".tif", ".tif",
".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": [ "ValidResolutions": [
"Original", "Original",
"176 x 176", "176 x 176",

View File

@ -67,7 +67,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -91,36 +90,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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" /> <PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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.Diagnostics;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Metadata.Models.Stateless; using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Property.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Shared.Models.Methods;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -11,7 +15,7 @@ namespace View_by_Distance.Metadata.Models;
/// <summary> /// <summary>
// Dictionary<string, List<KeyValuePair<string, string>>> // Dictionary<string, List<KeyValuePair<string, string>>>
/// </summary> /// </summary>
public class B_Metadata public class B_Metadata : IMetadata<MetadataExtractor.Directory>
{ {
private readonly Serilog.ILogger? _Log; private readonly Serilog.ILogger? _Log;
@ -21,6 +25,16 @@ public class B_Metadata
private readonly IReadOnlyDictionary<string, string[]> _FileGroups; private readonly IReadOnlyDictionary<string, string[]> _FileGroups;
private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; 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) public B_Metadata(IPropertyConfiguration propertyConfiguration, bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata, string bResultsFullGroupDirectory)
{ {
_Log = Serilog.Log.ForContext<B_Metadata>(); _Log = Serilog.Log.ForContext<B_Metadata>();
@ -49,12 +63,12 @@ public class B_Metadata
List<string> tagNames = new(); List<string> tagNames = new();
int type = (int)IExif.Tags.Orientation; int type = (int)IExif.Tags.Orientation;
string key = nameof(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) foreach (MetadataExtractor.Directory directory in directories)
{ {
if (!results.ContainsKey(directory.Name)) if (!results.ContainsKey(directory.Name))
results.Add(directory.Name, new()); results.Add(directory.Name, new());
foreach (MetadataExtractor.Tag tag in directory.Tags) foreach (Tag tag in directory.Tags)
{ {
tagNames.Add(tag.Name); tagNames.Add(tag.Name);
if (string.IsNullOrEmpty(tag.Description)) if (string.IsNullOrEmpty(tag.Description))
@ -80,11 +94,10 @@ public class B_Metadata
return results; 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(); List<KeyValuePair<string, string>> results = new();
string json = string.Empty; string json = string.Empty;
string[] changesFrom = new string[] { nameof(A_Property) };
Dictionary<string, List<KeyValuePair<string, string>>>? dictionary; Dictionary<string, List<KeyValuePair<string, string>>>? dictionary;
List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); 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); (_, 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); 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 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) => string? TestStatic_GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>
GetModel(directories); GetModel(directories);
static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) => static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories) =>

View File

@ -1,7 +1,5 @@
using MetadataExtractor; using MetadataExtractor;
using MetadataExtractor.Formats.Avi;
using MetadataExtractor.Formats.Exif; using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.QuickTime;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Metadata.Models.Stateless.Methods; namespace View_by_Distance.Metadata.Models.Stateless.Methods;
@ -53,106 +51,6 @@ internal class Metadata
return result; 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) internal static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
string? result; string? result;

View File

@ -67,7 +67,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -91,36 +90,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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" /> <PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Metadata\Metadata.csproj" />
<ProjectReference Include="..\Property\Property.csproj" /> <ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Resize\Resize.csproj" /> <ProjectReference Include="..\Resize\Resize.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" /> <ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />

View File

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

View File

@ -69,7 +69,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -93,36 +92,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Reflection; using System.Reflection;
using System.Text;
using View_by_Distance.Offset.Date.Time.Original.Models; 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.Methods;
using View_by_Distance.Shared.Models.Stateless; using View_by_Distance.Shared.Models.Stateless;
@ -14,6 +16,12 @@ namespace View_by_Distance.Offset.Date.Time.Original;
public class OffsetDateTimeOriginal public class OffsetDateTimeOriginal
{ {
private record Record(FileHolder FileHolder,
bool IsIgnoreExtension,
bool IsValidImageFormatExtension,
int Id,
DateTime DateTime);
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory; private readonly string _WorkingDirectory;
private readonly Configuration _Configuration; 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; 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); string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string file in files) foreach (string file in files)
{ {
property = Property.Models.A_Property.GetImageProperty(file); fileHolder = new(file);
if (property.Id is null || property.DateTimeOriginal is null) 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; continue;
dateTime = property.DateTimeOriginal.Value.AddTicks(ticks); dateTime = dateTimeOriginal.Value.AddTicks(ticks);
if (dateTime < minimumDateTime) if (dateTime < minimumDateTime)
continue; continue;
if (dateTime > maximumDateTime) if (dateTime > maximumDateTime)
continue; 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) if (files.Length != results.Count)
throw new Exception(); throw new Exception();
@ -85,14 +104,14 @@ public class OffsetDateTimeOriginal
#pragma warning disable CA1416 #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; Bitmap bitmap;
short type = 2; short type = 2;
string checkFile; string checkFile;
PropertyItem? propertyItem; PropertyItem? propertyItem;
string? ticksDirectory = null; string? ticksDirectory = null;
Shared.Models.Property property;
int dateTimeOriginal = (int)IExif.Tags.DateTimeOriginal; int dateTimeOriginal = (int)IExif.Tags.DateTimeOriginal;
for (int i = 0; i < int.MaxValue; i++) for (int i = 0; i < int.MaxValue; i++)
{ {
@ -104,26 +123,28 @@ public class OffsetDateTimeOriginal
} }
ticks++; 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(); 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 }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
ProgressBar progressBar = new(collection.Count, message, options); ProgressBar progressBar = new(records.Count, message, options);
foreach ((string file, int id, DateTime dateTime) in collection) foreach (Record record in records)
{ {
progressBar.Tick(); progressBar.Tick();
if (ticksDirectory is null) if (ticksDirectory is null)
throw new Exception(); throw new Exception();
checkFile = Path.Combine(ticksDirectory, Path.GetFileName(file)); checkFile = Path.Combine(ticksDirectory, record.FileHolder.Name);
if (File.Exists(checkFile)) if (File.Exists(checkFile))
continue; continue;
propertyItem = Shared.Models.Stateless.Methods.IProperty.GetPropertyItem(constructorInfo, dateTimeOriginal, type, dateTime.ToString("yyyy:MM:dd HH:mm:ss")); propertyItem = Property.Models.Stateless.IProperty.GetPropertyItem(constructorInfo, dateTimeOriginal, type, record.DateTime.ToString("yyyy:MM:dd HH:mm:ss"));
bitmap = new(file); bitmap = new(record.FileHolder.FullName);
bitmap.SetPropertyItem(propertyItem); bitmap.SetPropertyItem(propertyItem);
bitmap.Save(checkFile); bitmap.Save(checkFile);
bitmap.Dispose(); bitmap.Dispose();
property = Property.Models.A_Property.GetImageProperty(checkFile); (_, _, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, record.FileHolder, record.IsIgnoreExtension, record.IsValidImageFormatExtension, asciiEncoding);
if (property.Id is null || property.Id.Value != id) if (message is not null)
throw new Exception(message);
if (id is null || id.Value != record.Id)
throw new Exception(); throw new Exception();
} }
progressBar.Dispose(); progressBar.Dispose();
@ -131,13 +152,14 @@ public class OffsetDateTimeOriginal
#pragma warning restore CA1416 #pragma warning restore CA1416
private static void DateFix(ILogger log, string sourceDirectory) private void DateFix(ILogger log, string sourceDirectory)
{ {
string checkDirectory; string checkDirectory;
ASCIIEncoding asciiEncoding = new();
long oneYearTicks = DateTime.MinValue.AddYears(1).Ticks; long oneYearTicks = DateTime.MinValue.AddYears(1).Ticks;
checkDirectory = Path.Combine(sourceDirectory, oneYearTicks.ToString()); checkDirectory = Path.Combine(sourceDirectory, oneYearTicks.ToString());
if (Directory.Exists(checkDirectory)) 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 else
{ {
checkDirectory = Path.Combine(sourceDirectory, "1"); 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!"); log.Error("bad file(s) or target file(s) or maximum directory doesn't equal 1!");
else 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 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); 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()); (badDateTimeOriginal, badDateTimes, badId, badMessage) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, badFileHolder, badIsIgnoreExtension, badIsValidImageFormatExtension, asciiEncoding);
Shared.Models.Property targetProperty = Property.Models.A_Property.GetImageProperty(targetFiles.First()); if (badMessage is not null)
if (badProperty.DateTimeOriginal is null || targetProperty.DateTimeOriginal is 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!"); log.Error("Date is null!");
else else
{ {
TimeSpan timeSpan = new(targetProperty.DateTimeOriginal.Value.Ticks - badProperty.DateTimeOriginal.Value.Ticks); TimeSpan timeSpan = new(targetDateTimeOriginal.Value.Ticks - badDateTimeOriginal.Value.Ticks);
DateFix(sourceDirectory, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks); DateFix(sourceDirectory, asciiEncoding, checkDirectory, minimumDateTime, maximumDateTime, timeSpan.Ticks);
} }
} }
} }

View File

@ -66,7 +66,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -90,36 +89,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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": "{}", "ResultSingleton": "{}",
"RootDirectory": "/srv/samba/share", "RootDirectory": "/srv/samba/share",
"SaveDirectory": "/home/vscode", "SaveDirectory": "/home/vscode",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -43,36 +42,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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": "{}", "ResultSingleton": "{}",
"RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88", "RootDirectory": "C:/Tmp/Phares/Compare/Images-dd514b88",
"SaveDirectory": "D:/Tmp", "SaveDirectory": "D:/Tmp",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -165,36 +133,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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, "PopulatePropertyId": false,
"PropertiesChangedForProperty": false, "PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/Pictures", "RootDirectory": "C:/Tmp/Phares/Pictures",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -111,36 +110,6 @@
".tif", ".tif",
".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": [ "VerifyToSeason": [
". 2000", ". 2000",
". 2001", ". 2001",

View File

@ -1,14 +1,9 @@
using ShellProgressBar; using ShellProgressBar;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using View_by_Distance.Property.Models.Stateless; using View_by_Distance.Property.Models.Stateless;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.Property.Models; namespace View_by_Distance.Property.Models;
@ -62,201 +57,7 @@ public class A_Property
return result; return result;
} }
#pragma warning disable CA1416 private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension)
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)
{ {
Shared.Models.Property? result; Shared.Models.Property? result;
int? id = null; int? id = null;
@ -348,7 +149,7 @@ public class A_Property
if (result is null) if (result is null)
{ {
id ??= item.ImageFileHolder.Id; 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); json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true)) 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; 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; Shared.Models.Property property;
List<string> parseExceptions = new(); List<string> parseExceptions = new();
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.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}"); string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.ImageFileHolder.NameWithoutExtension}{item.ImageFileHolder.ExtensionLowered}");
if (item.IsValidImageFormatExtension && item.ImageFileHolder.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.ImageFileHolder.FullName != filteredSourceDirectoryFileExtensionLowered) if (item.IsValidImageFormatExtension && item.ImageFileHolder.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.ImageFileHolder.FullName != filteredSourceDirectoryFileExtensionLowered)
File.Move(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) 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) lock (sourceDirectoryChanges)
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now)); sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
lock (item) 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(); List<Tuple<string, DateTime>> sourceDirectoryFileTuples = new();
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
@ -409,7 +209,7 @@ public class A_Property
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
DateTime dateTime = DateTime.Now; DateTime dateTime = DateTime.Now;
List<Tuple<string, DateTime>> collection; 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()) if (i == 0 || sourceDirectoryChanges.Any())
progressBar.Tick(); progressBar.Tick();
lock (sourceDirectoryFileTuples) lock (sourceDirectoryFileTuples)
@ -452,7 +252,7 @@ public class A_Property
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName); 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) if (_Log is null)
throw new NullReferenceException(nameof(_Log)); throw new NullReferenceException(nameof(_Log));
@ -478,7 +278,7 @@ public class A_Property
SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName); SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName);
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); 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}"; 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) foreach (Exception exception in exceptions)
_Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception); _Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception);
if (exceptions.Count == container.Items.Count) 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; Shared.Models.Property result;
bool angleBracketCollectionAny = _AngleBracketCollection.Any(); bool angleBracketCollectionAny = _AngleBracketCollection.Any();
@ -509,9 +309,8 @@ public class A_Property
throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName)); throw new NullReferenceException(nameof(item.ImageFileHolder.DirectoryName));
SetAngleBracketCollection(item.ImageFileHolder.DirectoryName, !item.IsUniqueFileName); SetAngleBracketCollection(item.ImageFileHolder.DirectoryName, !item.IsUniqueFileName);
} }
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.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) if (!angleBracketCollectionAny)
_AngleBracketCollection.Clear(); _AngleBracketCollection.Clear();
return result; return result;

View File

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

View File

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

@ -24,4 +24,4 @@ public record AppSettings(string Company,
[JsonSerializable(typeof(AppSettings))] [JsonSerializable(typeof(AppSettings))]
internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

@ -66,4 +66,4 @@ public class AppSettings
[JsonSerializable(typeof(AppSettings))] [JsonSerializable(typeof(AppSettings))]
internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext
{ {
} }

View File

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

View File

@ -70,7 +70,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -94,36 +93,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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) 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); DateTime dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
string dateTimeValue = dateTime.ToString(dateTimeFormat); string dateTimeValue = dateTime.ToString(dateTimeFormat);
byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue); byte[] bytes = _ASCIIEncoding.GetBytes(dateTimeValue);

View File

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

View File

@ -2,6 +2,8 @@
using Phares.Shared; using Phares.Shared;
using Serilog; using Serilog;
using ShellProgressBar; using ShellProgressBar;
using System.Text;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Set.Created.Date.Models; using View_by_Distance.Set.Created.Date.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
@ -11,6 +13,8 @@ namespace View_by_Distance.Set.Created.Date;
public class SetCreatedDate public class SetCreatedDate
{ {
private record Record(FileHolder FileHolder, bool OriginalSet, DateTime DateTime);
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory; private readonly string _WorkingDirectory;
private readonly Configuration _Configuration; private readonly Configuration _Configuration;
@ -61,52 +65,76 @@ 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; int? id;
string? message; string? message;
DateTime? dateTime; DateTime[] dateTimes;
FileHolder fileHolder; FileHolder fileHolder;
DateTime?[] dateTimes;
bool isIgnoreExtension; bool isIgnoreExtension;
DateTime? dateTimeOriginal; DateTime? dateTimeOriginal;
bool isValidImageFormatExtension; bool isValidImageFormatExtension;
foreach (string file in files)
{
progressBar.Tick();
fileHolder = new(file);
if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
continue;
if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
continue;
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
if (isIgnoreExtension || !isValidImageFormatExtension)
continue;
(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) foreach (string[] files in filesCollection)
{ {
foreach (string file in files) 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)
{ {
progressBar.Tick(); if (record.DateTime == record.FileHolder.CreationTime)
fileHolder = new(file);
if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
continue; continue;
if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered)) if (record.OriginalSet)
continue; results.Add(new(record.FileHolder, record.OriginalSet, record.DateTime));
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); else
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); {
if (isIgnoreExtension || !isValidImageFormatExtension) minutes += 1;
continue; results.Add(new(record.FileHolder, record.OriginalSet, record.DateTime.AddMinutes(minutes)));
(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)
continue;
if (dateTime.Value == fileHolder.CreationTime)
continue;
results.Add((fileHolder, dateTime.Value));
} }
} }
return results; 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(); List<string> results = new();
foreach ((FileHolder fileHolder, DateTime dateTime) in toDoCollection) foreach (Record record in toDoCollection)
{ {
progressBar.Tick(); progressBar.Tick();
results.Add(fileHolder.NameWithoutExtension); results.Add(record.FileHolder.NameWithoutExtension);
try try
{ File.SetCreationTime(fileHolder.FullName, dateTime); } { File.SetCreationTime(record.FileHolder.FullName, record.DateTime); }
catch (Exception) { } catch (Exception) { }
} }
return results; return results;
@ -124,7 +152,7 @@ public class SetCreatedDate
int count = filesCollection.Select(l => l.Length).Sum(); int count = filesCollection.Select(l => l.Length).Sum();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
progressBar = new(count, message, options); progressBar = new(count, message, options);
List<(FileHolder, DateTime)> toDoCollection = GetToDoCollection(progressBar, filesCollection); List<Record> toDoCollection = GetToDoCollection(progressBar, filesCollection);
progressBar.Dispose(); progressBar.Dispose();
log.Information($"Ready to set created date {toDoCollection.Count} file(s)?"); log.Information($"Ready to set created date {toDoCollection.Count} file(s)?");
for (int y = 0; y < int.MaxValue; y++) for (int y = 0; y < int.MaxValue; y++)

View File

@ -68,7 +68,6 @@
"ResultContent": "()", "ResultContent": "()",
"ResultSingleton": "{}", "ResultSingleton": "{}",
"RootDirectory": "D:/Images", "RootDirectory": "D:/Images",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [ "IgnoreExtensions": [
".gif", ".gif",
".GIF", ".GIF",
@ -92,36 +91,6 @@
".TIFF", ".TIFF",
".tif", ".tif",
".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() => static int GetOffset() =>
1000000; 1000000;
int TestStatic_GetSortOrderOnlyLengthIndex() =>
GetSortOrderOnlyLengthIndex();
static int GetSortOrderOnlyLengthIndex() =>
GetOffset().ToString().Length + 3;
char TestStatic_GetDirectory(string fileName) => char TestStatic_GetDirectory(string fileName) =>
GetDirectory(fileName); GetDirectory(fileName);
static char GetDirectory(string fileName) => static char GetDirectory(string fileName) =>
@ -16,10 +21,23 @@ public interface IDirectory
static int GetDirectory(char directory) => static int GetDirectory(char directory) =>
directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11; directory == '-' ? 10 : int.TryParse(directory.ToString(), out int value) ? value : 11;
string TestStatic_GetPaddedId(int length, int index, int id) => string TestStatic_GetPaddedId(int intMinValueLength, int index, int id) =>
GetPaddedId(length, index, id); GetPaddedId(intMinValueLength, index, id);
static string GetPaddedId(int length, int index, int id) => static string GetPaddedId(int intMinValueLength, int index, int id) =>
id > -1 ? $"{index}070{id.ToString().PadLeft(length, '0')}" : $"{index}030{id.ToString()[1..].PadLeft(length, '0')}"; 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) => List<string[]> TestStatic_GetFilesCollection(string directory, string directorySearchFilter, string fileSearchFilter) =>
GetFilesCollection(directory, directorySearchFilter, fileSearchFilter); GetFilesCollection(directory, directorySearchFilter, fileSearchFilter);
@ -51,6 +69,11 @@ public interface IDirectory
static void MoveFiles(List<string> files, string find, string replace) => static void MoveFiles(List<string> files, string find, string replace) =>
XDirectory.MoveFiles(files, find, 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) => (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); 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) => 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; namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IProperty 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) => DateTime TestStatic_GetDateTime(Models.Property? property) =>
GetDateTime(property); GetDateTime(property);
static DateTime GetDateTime(Models.Property? 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) => static (bool?, string[]) IsWrongYear(Models.FileHolder fileHolder, DateTime? dateTimeOriginal, List<DateTime> dateTimes) =>
Property.IsWrongYear(fileHolder, dateTimeOriginal, 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) => bool TestStatic_NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) => static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
Property.NameWithoutExtensionIsIdFormat(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) => bool TestStatic_NameWithoutExtensionIsIdFormat(Models.FileHolder fileHolder) =>
NameWithoutExtensionIsIdFormat(fileHolder); NameWithoutExtensionIsIdFormat(fileHolder);
static bool NameWithoutExtensionIsIdFormat(Models.FileHolder 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) => 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); 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; namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Property internal abstract class Property
@ -24,25 +16,6 @@ internal abstract class Property
return result; 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) internal static (bool?, string[]) IsWrongYear(string[] segments, string year)
{ {
bool? result; bool? result;
@ -113,57 +86,6 @@ internal abstract class Property
return new(result, results); 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) internal static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp)
{ {
List<DateTime> results = new() List<DateTime> results = new()
@ -355,7 +277,8 @@ internal abstract class Property
internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension)
{ {
bool result; bool result;
if (fileNameWithoutExtension.Length < 5) int intMinValueLength = int.MinValue.ToString().Length;
if (fileNameWithoutExtension.Length < 5 || fileNameWithoutExtension.Length > intMinValueLength)
result = false; result = false;
else else
{ {
@ -365,181 +288,4 @@ internal abstract class Property
return result; 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 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) 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) else if (fromFileInfo.Length == toFileInfo.Length && fromFileInfo.LastWriteTime == toFileInfo.LastWriteTime)
checkDirectory = string.Concat(checkDirectory, ".del"); checkDirectory = string.Concat(checkDirectory, ".del");
else else
checkDirectory = string.Concat(checkDirectory, ".i"); checkDirectory = string.Concat(checkDirectory, ".j");
} }
File.Move(from, checkDirectory); File.Move(from, checkDirectory);
} }
@ -280,79 +280,91 @@ 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(); List<SortedRecord> results = new();
int? id; int? id;
short? multiplier; short? multiplier;
char negativeMarker; char negativeMarker;
int absoluteValueOfId; int absoluteValueOfId;
Models.FileHolder fileHolder; Models.FileHolder fileHolder;
int offset = IDirectory.GetOffset(); bool nameWithoutExtensionIsIdFormat;
int offsetLength = offset.ToString().Length; bool nameWithoutExtensionIsPaddedIdFormat;
int sortOrderOnlyLengthIndex = offsetLength + 3; int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
foreach (string[] files in filesCollection) foreach (string[] files in filesCollection)
{ {
foreach (string file in files) foreach (string file in files)
{ {
fileHolder = new Models.FileHolder(file); fileHolder = new Models.FileHolder(file);
if (!result) nameWithoutExtensionIsIdFormat = IProperty.NameWithoutExtensionIsIdFormat(fileHolder);
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
if (nameWithoutExtensionIsIdFormat)
{
multiplier = null; multiplier = null;
if (!int.TryParse(fileHolder.NameWithoutExtension, out absoluteValueOfId))
id = null;
else
id = absoluteValueOfId;
}
else if (!nameWithoutExtensionIsPaddedIdFormat)
{
id = null;
multiplier = null;
}
else else
{ {
if (fileHolder.NameWithoutExtension.Length < sortOrderOnlyLengthIndex) negativeMarker = fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex - 2];
{ if (negativeMarker == '7')
result = false; multiplier = 1;
else if (negativeMarker == '3')
multiplier = -1;
else
multiplier = null; multiplier = null;
} if (!int.TryParse(fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId))
id = null;
else else
{ {
negativeMarker = fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex - 2]; id = absoluteValueOfId * multiplier;
if (negativeMarker == '7') if (id is null || !fileHolder.NameWithoutExtension.EndsWith(id.Value.ToString()[1..]))
multiplier = 1; id = null;
else if (negativeMarker == '3')
multiplier = -1;
else
{
result = false;
multiplier = null;
}
} }
} }
if (!result) results.Add(new(fileHolder, nameWithoutExtensionIsIdFormat, id));
id = null;
else if (!int.TryParse(fileHolder.NameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId))
id = null;
else
id = absoluteValueOfId * multiplier;
results.Add(new(id, fileHolder));
} }
} }
return new(result, (from l in results orderby l.FileHolder.LastWriteTime, l.FileHolder.FullName.Length descending select l).ToArray()); 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) 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(); List<(Models.FileHolder, string)> results = new();
string paddedId;
string checkFile; string checkFile;
string directory; string directory;
FileInfo fileInfo; FileInfo fileInfo;
int directoryIndex; int directoryIndex;
string directoryName; string paddedIdFile;
bool wrapped = false; bool wrapped = false;
string directoryName;
bool paddedCheck = false;
SortedRecord sortedRecord;
Models.FileHolder fileHolder;
List<int> distinctIds = new(); List<int> distinctIds = new();
List<string> distinct = new(); List<string> distinct = new();
int offset = IDirectory.GetOffset();
List<string> distinctDirectories = new(); List<string> distinctDirectories = new();
(bool all, SortedRecord[] sortedRecords) = GetSortedRecords(filesCollection); int intMinValueLength = int.MinValue.ToString().Length;
foreach (SortedRecord sortedRecord in sortedRecords) SortedRecord[] sortedRecords = GetSortedRecords(filesCollection);
for (int i = 0; i < sortedRecords.Length; i++)
{ {
tick?.Invoke(); 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; continue;
(_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, sortedRecord.FileHolder.NameWithoutExtension); (_, directoryIndex) = IPath.GetDirectoryNameAndIndex(propertyConfiguration.ResultAllInOneSubdirectoryLength, fileHolder.NameWithoutExtension);
directoryName = Path.GetFileName(sortedRecord.FileHolder.DirectoryName); directoryName = Path.GetFileName(fileHolder.DirectoryName);
if (directoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !sortedRecord.FileHolder.Name.StartsWith(directoryName)) if (directoryName.Length < propertyConfiguration.ResultAllInOneSubdirectoryLength + 3 || !fileHolder.Name.StartsWith(directoryName))
{ {
if (wrapped) if (wrapped)
continue; continue;
@ -364,28 +376,35 @@ internal abstract partial class XDirectory
wrapped = true; wrapped = true;
directory = Path.Combine(directories[directoryIndex], directoryName); 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..])) paddedId = IDirectory.GetPaddedId(intMinValueLength, offset + i, sortedRecord.Id.Value);
throw new NotSupportedException(); 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) if (ifCanUseId)
checkFile = Path.Combine(directory, $"{sortedRecord.Id}{sortedRecord.FileHolder.ExtensionLowered}"); checkFile = Path.Combine(directory, $"{sortedRecord.Id}{fileHolder.ExtensionLowered}");
else 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 ((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; continue;
if (!copyDuplicates) if (!copyDuplicates)
continue; continue;
for (int i = 1; i < int.MaxValue; i++) for (int j = 1; j < int.MaxValue; j++)
{ {
fileInfo = new(checkFile); fileInfo = new(checkFile);
if (!fileInfo.Exists || sortedRecord.FileHolder.Length == fileInfo.Length && sortedRecord.FileHolder.LastWriteTime == fileInfo.LastWriteTime) if (!fileInfo.Exists || fileHolder.Length == fileInfo.Length && fileHolder.LastWriteTime == fileInfo.LastWriteTime)
checkFile = Path.Combine(directory, $"{sortedRecord.FileHolder.NameWithoutExtension}.{i}dup{sortedRecord.FileHolder.ExtensionLowered}"); checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}.{j}dup{fileHolder.ExtensionLowered}");
else 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 (sortedRecord.Id is not null)
{ {
if (distinctIds.Contains(sortedRecord.Id.Value)) if (distinctIds.Contains(sortedRecord.Id.Value))
@ -395,7 +414,7 @@ internal abstract partial class XDirectory
if (distinct.Contains(checkFile)) if (distinct.Contains(checkFile))
continue; continue;
distinct.Add(checkFile); distinct.Add(checkFile);
results.Add(new(sortedRecord.FileHolder, checkFile)); results.Add(new(fileHolder, checkFile));
if (!distinctDirectories.Contains(directory)) if (!distinctDirectories.Contains(directory))
distinctDirectories.Add(directory); distinctDirectories.Add(directory);
break; break;
@ -405,10 +424,12 @@ internal abstract partial class XDirectory
distinct.Add(checkFile); distinct.Add(checkFile);
if (sortedRecord.Id is not null) if (sortedRecord.Id is not null)
distinctIds.Add(sortedRecord.Id.Value); distinctIds.Add(sortedRecord.Id.Value);
results.Add(new(sortedRecord.FileHolder, checkFile)); results.Add(new(fileHolder, checkFile));
if (!distinctDirectories.Contains(directory)) if (!distinctDirectories.Contains(directory))
distinctDirectories.Add(directory); distinctDirectories.Add(directory);
} }
if (paddedCheck)
throw new Exception("Maybe need to restart application!");
return (distinctDirectories.ToArray(), results); return (distinctDirectories.ToArray(), results);
} }

View File

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