From 8ecea05fe8cdde168b0815a8f0ff4578a85b30b5 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 20 Jul 2025 18:46:59 -0700 Subject: [PATCH] xmp from my face-file after using the digiKam maintenance tool to create xmp files Alignment with Phares 8.0.118.14751 for Shared and Metadata --- .vscode/launch.json | 11 + .vscode/settings.json | 11 + ADO2025/PI6/.editorconfig | 6 +- ADO2025/PI6/Helper-2025-05-21.cs | 8 +- ADO2025/PI6/Helper-2025-06-01.cs | 1 - ADO2025/PI6/Helper-2025-06-28.cs | 1 - ADO2025/PI6/Helper-2025-07-01.cs | 15 +- ADO2025/PI6/Helper-2025-07-05.cs | 9 +- ADO2025/PI6/Helper-2025-07-09.cs | 6 +- ADO2025/PI6/Helper-2025-07-10.cs | 7 +- ADO2025/PI6/Helper-2025-07-20.cs | 427 +++++++++++++++ Day/HelperDay.cs | 2 + File-Folder-Helper.csproj | 8 +- Helpers/Exif/Dimensions.cs | 126 ----- Helpers/Exif/Exif.cs | 534 ------------------- Helpers/Exif/HelperExif.cs | 55 -- Helpers/ExifHelper.cs | 43 ++ Models/Exif/AviDirectory.cs | 24 - Models/Exif/ExifDirectory.cs | 36 -- Models/Exif/ExifDirectoryBase.cs | 66 --- Models/Exif/FileMetadataDirectory.cs | 23 - Models/Exif/GifHeaderDirectory.cs | 22 - Models/Exif/GpsDirectory.cs | 26 - Models/Exif/JpegDirectory.cs | 22 - Models/Exif/MakernoteDirectory.cs | 23 - Models/Exif/PhotoshopDirectory.cs | 22 - Models/Exif/PngDirectory.cs | 23 - Models/Exif/QuickTimeMovieHeaderDirectory.cs | 21 - Models/Exif/QuickTimeTrackHeaderDirectory.cs | 21 - Models/Exif/WebPDirectory.cs | 22 - Models/Face/FaceEncoding.cs | 11 - Models/Face/FaceFile.cs | 33 -- Models/Face/FacePart.cs | 54 -- Models/Face/FacePoint.cs | 39 -- Models/Face/Location.cs | 42 -- Models/Face/MappingFromPerson.cs | 24 - Models/Face/OutputResolution.cs | 5 - Worker.cs | 2 +- 38 files changed, 524 insertions(+), 1307 deletions(-) create mode 100644 ADO2025/PI6/Helper-2025-07-20.cs delete mode 100644 Helpers/Exif/Dimensions.cs delete mode 100644 Helpers/Exif/Exif.cs delete mode 100644 Helpers/Exif/HelperExif.cs create mode 100644 Helpers/ExifHelper.cs delete mode 100644 Models/Exif/AviDirectory.cs delete mode 100644 Models/Exif/ExifDirectory.cs delete mode 100644 Models/Exif/ExifDirectoryBase.cs delete mode 100644 Models/Exif/FileMetadataDirectory.cs delete mode 100644 Models/Exif/GifHeaderDirectory.cs delete mode 100644 Models/Exif/GpsDirectory.cs delete mode 100644 Models/Exif/JpegDirectory.cs delete mode 100644 Models/Exif/MakernoteDirectory.cs delete mode 100644 Models/Exif/PhotoshopDirectory.cs delete mode 100644 Models/Exif/PngDirectory.cs delete mode 100644 Models/Exif/QuickTimeMovieHeaderDirectory.cs delete mode 100644 Models/Exif/QuickTimeTrackHeaderDirectory.cs delete mode 100644 Models/Exif/WebPDirectory.cs delete mode 100644 Models/Face/FaceEncoding.cs delete mode 100644 Models/Face/FaceFile.cs delete mode 100644 Models/Face/FacePart.cs delete mode 100644 Models/Face/FacePoint.cs delete mode 100644 Models/Face/Location.cs delete mode 100644 Models/Face/MappingFromPerson.cs delete mode 100644 Models/Face/OutputResolution.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index 2354205..b48fb02 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,6 +11,17 @@ "preLaunchTask": "build", "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll", "args": [ + "s", + "X", + "V:/Tmp/Phares/Helper-2025-07-20", + "Day-Helper-2025-07-20", + "871467010009.jpg", + "L:/Git/AA/Rename/.vscode/.UserSecrets/secrets.json", + "A:/()/638432064000000000.51/1401-08-03_02/2023/X+441981864000000000/871467010009.444090906.jpg.png", + "*.png", + "D:/{}/DisneyWorld 2019/Magic Kingdom/871467010009.jpg.xmp", + "*.xmp", + "{}-output", "s", "X", "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/Log", diff --git a/.vscode/settings.json b/.vscode/settings.json index d7f8761..1144a57 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,12 @@ { + "files.associations": { + "*.container": "ini", + "*.org": "ini", + "*.net": "ini", + "*.xmp": "xml", + "podman": "ini", + "default": "ini" + }, "[markdown]": { "editor.wordWrap": "off" }, @@ -17,6 +25,7 @@ "BIRT", "CHIL", "DEAT", + "digi", "endianness", "Exif", "FAMC", @@ -32,8 +41,10 @@ "kanbn", "Kofax", "Linc", + "Makernote", "mesfs", "mestsa", + "mklink", "netrm", "NpgSql", "NSFX", diff --git a/ADO2025/PI6/.editorconfig b/ADO2025/PI6/.editorconfig index 7e45061..5554fbd 100644 --- a/ADO2025/PI6/.editorconfig +++ b/ADO2025/PI6/.editorconfig @@ -325,7 +325,7 @@ dotnet_diagnostic.CA2211.severity = none # Question - Non-constant fields should dotnet_diagnostic.CA2249.severity = none # Question - Use dotnet_diagnostic.CA2253.severity = none # Question - Named placeholders should not be numeric values dotnet_diagnostic.CS0103.severity = none # Question - The name -dotnet_diagnostic.CS0168.severity = none # Question - The variable +dotnet_diagnostic.CS0168.severity = warning # Question - The variable dotnet_diagnostic.CS0219.severity = none # Question - The variable dotnet_diagnostic.CS0612.severity = none # Question - is obsolete dotnet_diagnostic.CS0618.severity = none # Question - Compiler Warning (level 2) @@ -337,7 +337,7 @@ dotnet_diagnostic.CS8603.severity = none # Question - Possible null reference re dotnet_diagnostic.CS8604.severity = none # Question - Possible null reference argument for parameter. dotnet_diagnostic.CS8618.severity = none # Question - Non-nullable variable must contain a non-null value when exiting constructor dotnet_diagnostic.CS8625.severity = none # Question - Cannot convert null literal to non-nullable reference type. -dotnet_diagnostic.CS8629.severity = none # Question - Nullable value type may be null +dotnet_diagnostic.CS8629.severity = warning # Question - Nullable value type may be null dotnet_diagnostic.CS8765.severity = none # Question - Nullability of type of parameter dotnet_diagnostic.IDE0005.severity = none # Question - Remove unnecessary using directives dotnet_diagnostic.IDE0008.severity = warning # Question - Use explicit type instead of @@ -361,7 +361,7 @@ dotnet_diagnostic.IDE0055.severity = none # Question - Formatting rule dotnet_diagnostic.IDE0057.severity = none # Question - Substring can be simplified dotnet_diagnostic.IDE0058.severity = none # Question - Remove unnecessary expression value dotnet_diagnostic.IDE0059.severity = none # Question - Unnecessary assignment of a value to -dotnet_diagnostic.IDE0060.severity = none # Question - Remove unused parameter +dotnet_diagnostic.IDE0060.severity = warning # Question - Remove unused parameter dotnet_diagnostic.IDE0063.severity = none # Question - Use simple dotnet_diagnostic.IDE0065.severity = none # Question - dotnet_diagnostic.IDE0066.severity = none # Question - Use diff --git a/ADO2025/PI6/Helper-2025-05-21.cs b/ADO2025/PI6/Helper-2025-05-21.cs index dde272e..31e5e90 100644 --- a/ADO2025/PI6/Helper-2025-05-21.cs +++ b/ADO2025/PI6/Helper-2025-05-21.cs @@ -50,7 +50,12 @@ internal static partial class Helper20250521 { } internal static void MatchDirectory(ILogger logger, List args) { - Record record; + logger.LogInformation(args[0]); + logger.LogInformation(args[1]); + logger.LogInformation(args[2]); + logger.LogInformation(args[3]); + logger.LogInformation(args[4]); + logger.LogInformation(args[5]); string datePattern = args[5]; string searchPattern = args[2]; string searchPatternB = args[3]; @@ -119,7 +124,6 @@ internal static partial class Helper20250521 { private static RecordB? GetRecord(int dateLineSegmentCount, string datePattern, string[] lines, int i, string[] segments, DateTime transactionDate, DateTime effectiveDate) { RecordB? result = null; string line; - RecordB record; LineCheck lineCheck; List collection = []; for (int j = i + 1; j < lines.Length; j++) { diff --git a/ADO2025/PI6/Helper-2025-06-01.cs b/ADO2025/PI6/Helper-2025-06-01.cs index 4e058e8..56e3df3 100644 --- a/ADO2025/PI6/Helper-2025-06-01.cs +++ b/ADO2025/PI6/Helper-2025-06-01.cs @@ -36,7 +36,6 @@ internal static partial class Helper20250601 { internal static void EquipmentAutomationFrameworkStatus(ILogger logger, List args) { Status status; Record? record; - List messages; logger.LogInformation(args[0]); logger.LogInformation(args[1]); logger.LogInformation(args[2]); diff --git a/ADO2025/PI6/Helper-2025-06-28.cs b/ADO2025/PI6/Helper-2025-06-28.cs index 5529661..1f2d3e7 100644 --- a/ADO2025/PI6/Helper-2025-06-28.cs +++ b/ADO2025/PI6/Helper-2025-06-28.cs @@ -26,7 +26,6 @@ internal static partial class Helper20250628 { private static ReadOnlyCollection GetRecords(string[] searchPatternFiles) { List results = []; Record record; - string[] files; FileInfo fileInfo; foreach (string searchPatternFile in searchPatternFiles) { fileInfo = new(searchPatternFile); diff --git a/ADO2025/PI6/Helper-2025-07-01.cs b/ADO2025/PI6/Helper-2025-07-01.cs index abeb462..a6595df 100644 --- a/ADO2025/PI6/Helper-2025-07-01.cs +++ b/ADO2025/PI6/Helper-2025-07-01.cs @@ -52,7 +52,6 @@ internal static partial class Helper20250701 { string[] files; string markdown; string checkFile; - string[] matches; FileInfo fileInfo; string? pipeTable; string? collections; @@ -102,7 +101,7 @@ internal static partial class Helper20250701 { logger.LogWarning("json is null"); continue; } - pipeTable = GetPipeTable(logger, json); + pipeTable = GetPipeTable(json); if (string.IsNullOrEmpty(pipeTable)) { logger.LogWarning("pipeTable is null"); continue; @@ -137,7 +136,7 @@ internal static partial class Helper20250701 { if (lines.Length < columnTitlesLine.Value + 1) { logger.LogWarning("<{lines}>(s)", lines.Length); } else { - result = GetMarkdown(timeColumn, columnMapping, name, lines, columnTitlesLine); + result = GetMarkdown(timeColumn, columnMapping, name, lines, columnTitlesLine.Value); } } return result; @@ -156,7 +155,6 @@ internal static partial class Helper20250701 { private static ReadOnlyDictionary> GetKeyValuePairs(int columnTitlesLine, string[] lines) { Dictionary> results = []; - string value; string[] segments; List> collections = []; string[] columns = lines[columnTitlesLine].Split('\t'); @@ -189,11 +187,11 @@ internal static partial class Helper20250701 { return results.AsReadOnly(); } - private static string? GetMarkdown(string timeColumn, ReadOnlyDictionary columnMapping, string name, string[] lines, int? columnTitlesLine) { + private static string? GetMarkdown(string timeColumn, ReadOnlyDictionary columnMapping, string name, string[] lines, int columnTitlesLine) { string? result; List charts = []; List results = []; - ReadOnlyDictionary> keyValuePairs = GetKeyValuePairs(columnTitlesLine.Value, lines); + ReadOnlyDictionary> keyValuePairs = GetKeyValuePairs(columnTitlesLine, lines); string[] columns = keyValuePairs.Keys.OrderBy(l => l).ToArray(); if (!columns.Contains(timeColumn)) { result = null; @@ -227,10 +225,9 @@ internal static partial class Helper20250701 { if (results.Count == 0 && charts.Count == 0) { result = null; } else { - string[] segments; results.Add($"## Footer{Environment.NewLine}"); results.Insert(0, $"# {name}{Environment.NewLine}"); - for (int i = columnTitlesLine.Value + 1; i < lines.Length; i++) { + for (int i = columnTitlesLine + 1; i < lines.Length; i++) { if (lines[i].StartsWith("NUM_DATA_ROWS")) { for (int j = i; j < lines.Length; j++) { results.Add($"- {lines[j]}"); @@ -388,7 +385,7 @@ internal static partial class Helper20250701 { return results.AsReadOnly(); } - private static string? GetPipeTable(ILogger logger, string json) { + private static string? GetPipeTable(string json) { string? result = null; string? value; string[]? columns = null; diff --git a/ADO2025/PI6/Helper-2025-07-05.cs b/ADO2025/PI6/Helper-2025-07-05.cs index 721a77a..6f37aea 100644 --- a/ADO2025/PI6/Helper-2025-07-05.cs +++ b/ADO2025/PI6/Helper-2025-07-05.cs @@ -1,4 +1,3 @@ - using System.Drawing; using Microsoft.Extensions.Logging; @@ -94,19 +93,23 @@ internal static partial class Helper20250705 { height: rectangleFHeight, left: rectangleFLeft, top: rectangleFTop, - suffix: $"-{i}whole-percentages.jpg"); + suffix: $"-{i}-whole-percentages.jpg"); } } } private static void Extract(string file, float width, float height, double left, double top, string suffix) { +#if SystemDrawingCommon RectangleF rectangle = new((float)left, (float)top, width, height); using (Bitmap source = new(file)) { using (Bitmap bitmap = new((int)width, (int)height)) { - using (Graphics graphics = Graphics.FromImage(bitmap)) + using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.DrawImage(source, new RectangleF(0, 0, width, height), rectangle, GraphicsUnit.Pixel); + } bitmap.Save($"{file}{suffix}"); } } +#endif } + } \ No newline at end of file diff --git a/ADO2025/PI6/Helper-2025-07-09.cs b/ADO2025/PI6/Helper-2025-07-09.cs index 336857a..7aff2bd 100644 --- a/ADO2025/PI6/Helper-2025-07-09.cs +++ b/ADO2025/PI6/Helper-2025-07-09.cs @@ -154,7 +154,6 @@ internal static partial class Helper20250709 { logger.LogInformation(args[3]); logger.LogInformation(args[4]); logger.LogInformation(args[5]); - string[] segments; string extension = args[4]; string searchPattern = args[2]; int sizeFilter = int.Parse(args[3]); @@ -162,13 +161,12 @@ internal static partial class Helper20250709 { string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]); string destinationDirectory = Path.GetFullPath(args[6].Split('~')[0]); string[] directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly); - JavaScriptObjectNotationTo(logger, sourceDirectory, searchPattern, sizeFilter, extension, columns.AsReadOnly(), destinationDirectory, directories.AsReadOnly()); + JavaScriptObjectNotationTo(sourceDirectory, searchPattern, sizeFilter, extension, destinationDirectory, directories.AsReadOnly()); Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory); } - private static void JavaScriptObjectNotationTo(ILogger logger, string sourceDirectory, string searchPattern, int sizeFilter, string extension, ReadOnlyCollection columnMapping, string destinationDirectory, ReadOnlyCollection directories) { + private static void JavaScriptObjectNotationTo(string sourceDirectory, string searchPattern, int sizeFilter, string extension, string destinationDirectory, ReadOnlyCollection directories) { Raw? raw; - string text; string json; string[] files; string checkFile; diff --git a/ADO2025/PI6/Helper-2025-07-10.cs b/ADO2025/PI6/Helper-2025-07-10.cs index a1d4233..2f9dfb2 100644 --- a/ADO2025/PI6/Helper-2025-07-10.cs +++ b/ADO2025/PI6/Helper-2025-07-10.cs @@ -15,17 +15,15 @@ internal static partial class Helper20250710 { logger.LogInformation(args[1]); logger.LogInformation(args[2]); logger.LogInformation(args[3]); - string[] segments; string searchPattern = args[3]; string directoryPattern = args[2]; string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]); string[] directories = Directory.GetDirectories(sourceDirectory, directoryPattern, SearchOption.TopDirectoryOnly); - LogToTrace(logger, sourceDirectory, searchPattern, directories.AsReadOnly()); + LogToTrace(logger, searchPattern, directories.AsReadOnly()); Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory); } - private static void LogToTrace(ILogger logger, string sourceDirectory, string searchPattern, ReadOnlyCollection directories) { - string text; + private static void LogToTrace(ILogger logger, string searchPattern, ReadOnlyCollection directories) { string[] lines; string[] files; string checkFile; @@ -55,7 +53,6 @@ internal static partial class Helper20250710 { Match match; string body; string[] segments; - string previousLine; List log = []; for (int i = 1; i < lines.Length - 1; i++) { line = lines[i]; diff --git a/ADO2025/PI6/Helper-2025-07-20.cs b/ADO2025/PI6/Helper-2025-07-20.cs new file mode 100644 index 0000000..6b08e42 --- /dev/null +++ b/ADO2025/PI6/Helper-2025-07-20.cs @@ -0,0 +1,427 @@ +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Text.Json; + +using Microsoft.Extensions.Logging; + +using Phares.Metadata.Models.Stateless; +using Phares.Shared.Models; + +namespace File_Folder_Helper.ADO2025.PI6; + +internal static partial class Helper20250720 { + + internal static void WriteFaceData(ILogger logger, List args) { + logger.LogInformation(args[0]); + logger.LogInformation(args[1]); + logger.LogInformation(args[2]); + logger.LogInformation(args[3]); + logger.LogInformation(args[4]); + logger.LogInformation(args[5]); + logger.LogInformation(args[6]); + logger.LogInformation(args[6]); + logger.LogInformation(args[7]); + logger.LogInformation(args[8]); + string searchPattern = args[5]; + string searchPatternXMP = args[7]; + string outputDirectoryName = args[8]; + string jsonFile = Path.GetFullPath(args[3]); + string digiKamFile = Path.GetFullPath(args[6]); + FileInfo faceFileInfo = new(Path.GetFullPath(args[4])); + string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]); + string pathRoot = Path.GetPathRoot(faceFileInfo.FullName) ?? throw new Exception(); + string? checkDirectory = Path.GetDirectoryName(digiKamFile.Replace("{}", outputDirectoryName)); + string originalFile = Path.Combine(sourceDirectory, args[2]); + string pathRootXMP = digiKamFile[..5]; + if (!File.Exists(jsonFile)) { + logger.LogError("json file doesn't exist! <{jsonFile}>", jsonFile); + } else if (!File.Exists(digiKamFile)) { + logger.LogError("digiKam file doesn't exist! <{digiKamFile}>", digiKamFile); + } else if (!File.Exists(originalFile)) { + logger.LogError("Original file doesn't exist! <{checkFile}>", originalFile); + } else if (!Directory.Exists(checkDirectory)) { + logger.LogError("checkDirectory doesn't exist! <{checkDirectory}>", checkDirectory); + } else if (!faceFileInfo.Exists) { + logger.LogError("Face file doesn't exist! <{faceFileInfo}>", faceFileInfo.FullName); + } else { + string json = File.ReadAllText(jsonFile); + ResultSettings? resultSettings = JsonSerializer.Deserialize(json, ResultSettingsSourceGenerationContext.Default.ResultSettings); + MetadataSettings? metadataSettings = JsonSerializer.Deserialize(json, MetadataSettingsSourceGenerationContext.Default.MetadataSettings); + if (resultSettings is null) { + logger.LogError(nameof(ResultSettings)); + } else if (metadataSettings is null) { + logger.LogError(nameof(MetadataSettings)); + } else { + WriteFaceData(logger, outputDirectoryName, originalFile, faceFileInfo, digiKamFile, resultSettings, metadataSettings); + ReadOnlyDictionary> keyValuePairsXMP = GetKeyValuePairs(searchPatternXMP, pathRootXMP); + ReadOnlyDictionary> keyValuePairs = GetKeyValuePairs(searchPattern, pathRoot, resultSettings, metadataSettings); + if (keyValuePairs.Count == 0) { + logger.LogError("Didn't find any valid file(s)!"); + } else { + WriteFaceData(logger, outputDirectoryName, keyValuePairs, keyValuePairsXMP); + } + } + } + } + + private static void WriteFaceData(ILogger logger, string outputDirectoryName, string originalFile, FileInfo faceFileInfo, string digiKamFile, ResultSettings resultSettings, MetadataSettings metadataSettings) { + ExifDirectory? exifDirectory = IMetadata.GetExifDirectory(resultSettings, metadataSettings, faceFileInfo); + if (exifDirectory is null) { + logger.LogError("exifDirectory is null!"); + } else { + long id; + string fileNameWithoutExtension; + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(faceFileInfo.FullName); + if (!long.TryParse(fileNameWithoutExtension.Split('.')[0], out id)) { + id = -1; + } + long? fileNameFirstSegment = id == -1 ? null : id; + ReadOnlyCollection digiKamFiles = new([digiKamFile]); + ReadOnlyCollection exifDirectories = new([exifDirectory]); + WriteFaceData(logger, outputDirectoryName, originalFile, fileNameFirstSegment, exifDirectories, digiKamFiles); + } + } + + private static void WriteFaceData(ILogger logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection exifDirectories, ReadOnlyCollection digiKamFiles) { + ReadOnlyDictionary keyValuePairs = GetKeyValuePairs(logger, exifDirectories); + if (keyValuePairs.Count > 0) { + WriteFaceData(logger, outputDirectoryName, originalFile, fileNameFirstSegment, digiKamFiles, keyValuePairs); + } + } + + private static int? GetMatchingLine(string digiKamLine, ReadOnlyCollection lines) { + int? result = null; + for (int i = 0; i < lines.Count; i++) { + if (lines[i] == digiKamLine) { + result = i; + break; + } + } + return result; + } + + private static void WriteFaceData(string outputDirectoryName, string? originalFile, ReadOnlyDictionary keyValuePairs, string digiKamFile, List trimmed, int rdfLine) { + if (keyValuePairs.Count == 0) { + throw new Exception(); + } + double h; + double w; + double mpTop; + double width; + double height; + double mpLeft; + double mwgTop; + double mwgLeft; + string personKey; + FaceFile faceFile; + string descriptionLine = ""; + faceFile = keyValuePairs.ElementAt(0).Value; + List regionLines = [ + "", + "", + "" + ]; + List regionsLinesB = [ + "", + "", + "", + "" + ]; + List digiKamLines = ["", ""]; + List microsoftPhotoLines = ["", ""]; + List hierarchicalSubjectLines = ["", ""]; + List catalogSetLines = ["", ""]; + List subjectLines = ["", ""]; + foreach (KeyValuePair keyValuePair in keyValuePairs) { + personKey = keyValuePair.Key; + faceFile = keyValuePair.Value; + width = faceFile.Location.Right - faceFile.Location.Left; + height = faceFile.Location.Bottom - faceFile.Location.Top; + if (!string.IsNullOrEmpty(originalFile) && File.Exists(originalFile)) { + Extract(file: originalFile, + width: width, + height: height, + left: faceFile.Location.Left, + top: faceFile.Location.Top, + suffix: $"-{keyValuePair.Key}-whole-percentages.jpg"); + } + w = width / faceFile.OutputResolution.Width; + h = height / faceFile.OutputResolution.Height; + if (w == 0 || h == 0) + throw new NotImplementedException(); + mpLeft = (double)faceFile.Location.Left / faceFile.OutputResolution.Width; + mpTop = (double)faceFile.Location.Top / faceFile.OutputResolution.Height; + mwgLeft = (faceFile.Location.Left + (width * .5)) / faceFile.OutputResolution.Width; + mwgTop = (faceFile.Location.Top + (height * .5)) / faceFile.OutputResolution.Height; + // + // + // + // + // + // + // + regionLines.Add(""); + // + // + // + // + // + // + // + // + // + // + // + // + regionsLinesB.Add(""); + regionsLinesB.Add(""); + regionsLinesB.Add(""); + regionsLinesB.Add(""); + regionsLinesB.Add(""); + // + // + // People/{personKey} + // + // + digiKamLines.Add($"People/{personKey}"); + // + // + // People/{personKey} + // + // + microsoftPhotoLines.Add($"People/{personKey}"); + // + // + // People|{personKey} + // + // + hierarchicalSubjectLines.Add($"People|{personKey}"); + // + // + // People|{personKey} + // + // + catalogSetLines.Add($"People|{personKey}"); + // + // + // {personKey} + // + // + subjectLines.Add($"{personKey}"); + } + regionLines.AddRange(["","",""]); + regionsLinesB.AddRange(["", "",""]); + digiKamLines.AddRange(["", ""]); + microsoftPhotoLines.AddRange(["", ""]); + hierarchicalSubjectLines.AddRange(["", ""]); + catalogSetLines.AddRange(["", ""]); + subjectLines.AddRange(["", ""]); + List lines = []; + lines.AddRange(regionLines); + lines.AddRange(regionsLinesB); + lines.AddRange(digiKamLines); + lines.AddRange(microsoftPhotoLines); + lines.AddRange(hierarchicalSubjectLines); + lines.AddRange(catalogSetLines); + lines.AddRange(subjectLines); + string text = string.Join(Environment.NewLine, lines); + if (trimmed[rdfLine - 1] != descriptionLine) { + trimmed[rdfLine - 1] = $"{trimmed[rdfLine - 1][..^2]}>"; + trimmed.Insert(rdfLine, descriptionLine); + rdfLine++; + } + trimmed.Insert(rdfLine - 1, text); + string allText = string.Join(Environment.NewLine, trimmed); + File.WriteAllText(digiKamFile.Replace("{}", outputDirectoryName), allText); + if (!string.IsNullOrEmpty(originalFile)) { + if (Debugger.IsAttached) { + File.WriteAllText(".xml", allText); + } + } + } + + private static ReadOnlyDictionary> GetKeyValuePairs(string searchPattern, string pathRoot) { + Dictionary> results = []; + long fileNameFirstSegment; + List? collection; + string fileNameWithoutExtension; + Dictionary> keyValuePairs = []; + string[] files = Directory.GetFiles(pathRoot, searchPattern, SearchOption.AllDirectories); + foreach (string file in files) { + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); + if (!long.TryParse(fileNameWithoutExtension.Split('.')[0], out fileNameFirstSegment)) { + continue; + } + if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) { + keyValuePairs.Add(fileNameFirstSegment, []); + if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) { + throw new Exception(); + } + } + collection.Add(file); + } + foreach (KeyValuePair> keyValuePair in keyValuePairs) { + results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly()); + } + return results.AsReadOnly(); + } + + private static ReadOnlyDictionary GetKeyValuePairs(ILogger logger, ReadOnlyCollection exifDirectories) { + Dictionary results = []; + string personKey; + FaceFile? faceFile; + foreach (ExifDirectory exifDirectory in exifDirectories) { + faceFile = IMetadata.GetFaceFile(exifDirectory); + if (faceFile is null) { + logger.LogError("faceFile is null!"); + } else if (faceFile.Location is null) { + logger.LogError("faceFile location is null!"); + } else if (faceFile.OutputResolution?.Orientation is not 0 and not 1) { + logger.LogWarning("faceFile output-resolution orientation is not aloud!"); + } else { + personKey = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(exifDirectory.FilePath.FullName)))); + if (results.ContainsKey(personKey)) { + continue; + } + results.Add(personKey, faceFile); + } + } + return results.AsReadOnly(); + } + + private static ReadOnlyDictionary> GetKeyValuePairs(string searchPattern, string pathRoot, ResultSettings resultSettings, MetadataSettings metadataSettings) { + Dictionary> results = []; + FileInfo faceFileInfo; + long fileNameFirstSegment; + ExifDirectory? exifDirectory; + List? collection; + string fileNameWithoutExtension; + Dictionary> keyValuePairs = []; + string[] files = Directory.GetFiles(pathRoot, searchPattern, SearchOption.AllDirectories); + foreach (string file in files) { + faceFileInfo = new(file); + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(faceFileInfo.FullName); + if (!long.TryParse(fileNameWithoutExtension.Split('.')[0], out fileNameFirstSegment)) { + continue; + } + exifDirectory = IMetadata.GetExifDirectory(resultSettings, metadataSettings, faceFileInfo); + if (exifDirectory is null) + continue; + if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) { + keyValuePairs.Add(fileNameFirstSegment, []); + if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) + throw new Exception(); + } + collection.Add(exifDirectory); + } + foreach (KeyValuePair> keyValuePair in keyValuePairs) { + results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly()); + } + return results.AsReadOnly(); + } + + private static void WriteFaceData(ILogger logger, string outputDirectoryName, ReadOnlyDictionary> keyValuePairs, ReadOnlyDictionary> keyValuePairsXMP) { + ReadOnlyCollection? digiKamFiles; + foreach (KeyValuePair> keyValuePair in keyValuePairs) { + if (!keyValuePairsXMP.TryGetValue(keyValuePair.Key, out digiKamFiles)) { + logger.LogWarning("{fileNameFirstSegment}) Didn't find a matching file!", keyValuePair.Key); + } else { + string? originalFile = null; + WriteFaceData(logger, outputDirectoryName, originalFile, keyValuePair.Key, keyValuePair.Value, digiKamFiles); + } + } + } + + private static void WriteFaceData(ILogger logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection digiKamFiles, ReadOnlyDictionary keyValuePairs) { +#if xmp + IXmpMeta xmp; + using FileStream stream = File.OpenRead(digiKamFile); + xmp = XmpMetaFactory.Parse(stream); + foreach (var property in xmp.Properties) { + logger.LogDebug("Path={property.Path} Namespace={property.Namespace} Value={property.Value}", property.Path, property.Namespace, property.Value); + } + xmp.Sort(); + SerializeOptions serializeOptions = new(SerializeOptions.EncodeUtf8); + string check = XmpMetaFactory.SerializeToString(xmp, serializeOptions); + File.WriteAllText(".xmp", check); +#endif + string[] requiredLines = [ + "xmlns:digiKam=\"http://www.digikam.org/ns/1.0/\"", + "xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"", + "xmlns:exif=\"http://ns.adobe.com/exif/1.0/\"", + "xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\"", + "xmlns:dc=\"http://purl.org/dc/elements/1.1/\"", + "xmlns:acdsee=\"http://ns.acdsee.com/iptc/1.0/\"", + "xmlns:lr=\"http://ns.adobe.com/lightroom/1.0/\"", + "xmlns:MP=\"http://ns.microsoft.com/photo/1.2/\"", + "xmlns:stArea=\"http://ns.adobe.com/xmp/sType/Area#\"", + "xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\"", + "xmlns:MicrosoftPhoto=\"http://ns.microsoft.com/photo/1.0/\"", + "xmlns:MPReg=\"http://ns.microsoft.com/photo/1.2/t/Region#\"", + "xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimensions#\"", + "xmlns:MPRI=\"http://ns.microsoft.com/photo/1.2/t/RegionInfo#\"", + "xmlns:mediapro=\"http://ns.iview-multimedia.com/mediapro/1.0/\"", + "xmlns:mwg-rs=\"http://www.metadataworkinggroup.com/schemas/regions/\"", + "" + ]; + foreach (string digiKamFile in digiKamFiles) { + string[] lines = File.ReadAllLines(digiKamFile); + List trimmed = lines.Select(l => l.Trim()).ToList(); + int? digiKamLine = GetMatchingLine(requiredLines[0], trimmed.AsReadOnly()); + if (digiKamLine is null) { + logger.LogError("{fileNameFirstSegment}) Didn't fine digiKam line!", fileNameFirstSegment); + } else { + foreach (string requiredLine in requiredLines) { + if (!trimmed.Contains(requiredLine)) { + trimmed.Insert(digiKamLine.Value + 1, requiredLine); + } + } + int? rdfLine = GetMatchingLine(requiredLines[^1], trimmed.AsReadOnly()); + if (rdfLine is null) { + logger.LogError("{fileNameFirstSegment}) Didn't fine description line!", fileNameFirstSegment); + } else { + WriteFaceData(outputDirectoryName, originalFile, keyValuePairs, digiKamFile, trimmed, rdfLine.Value); + } + } + } + } + + private static void Extract(string file, double width, double height, int left, int top, string suffix) { +#if SystemDrawingCommon + Rectangle rectangle = new(left, top, width, height); + using (Bitmap source = new(file)) { + using (Bitmap bitmap = new(width, height)) { + using (Graphics graphics = Graphics.FromImage(bitmap)) { + graphics.DrawImage(source, new Rectangle(0, 0, width, height), rectangle, GraphicsUnit.Pixel); + } + bitmap.Save($"{file}{suffix}"); + } + } +#endif + } + +} \ No newline at end of file diff --git a/Day/HelperDay.cs b/Day/HelperDay.cs index fa6be2a..12aa7db 100644 --- a/Day/HelperDay.cs +++ b/Day/HelperDay.cs @@ -181,6 +181,8 @@ internal static class HelperDay ADO2025.PI6.Helper20250709.JavaScriptObjectNotationToReactor(logger, args); else if (args[1] == "Day-Helper-2025-07-10") ADO2025.PI6.Helper20250710.StripLog(logger, args); + else if (args[1] == "Day-Helper-2025-07-20") + ADO2025.PI6.Helper20250720.WriteFaceData(logger, args); else throw new Exception(appSettings.Company); } diff --git a/File-Folder-Helper.csproj b/File-Folder-Helper.csproj index fbe8106..f69b7d2 100644 --- a/File-Folder-Helper.csproj +++ b/File-Folder-Helper.csproj @@ -14,12 +14,12 @@ - - - - + + + + diff --git a/Helpers/Exif/Dimensions.cs b/Helpers/Exif/Dimensions.cs deleted file mode 100644 index ed7f524..0000000 --- a/Helpers/Exif/Dimensions.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System.Drawing; - -namespace File_Folder_Helper.Helpers.Exif; - -internal static class Dimensions -{ - -#pragma warning disable IDE0230 - private static readonly Dictionary> _ImageFormatDecoders = new() - { - { new byte[] { 0x42, 0x4D }, DecodeBitmap }, - { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif }, - { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif }, - { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng }, - { new byte[] { 0xff, 0xd8 }, DecodeJfif }, - { new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP }, - }; -#pragma warning restore IDE0230 - - private static bool StartsWith(byte[] thisBytes, byte[] thatBytes) - { - for (int i = 0; i < thatBytes.Length; i += 1) - { - if (thisBytes[i] == thatBytes[i]) - continue; - return false; - } - return true; - } - - private static short ReadLittleEndianInt16(BinaryReader binaryReader) - { - byte[] bytes = new byte[sizeof(short)]; - for (int i = 0; i < sizeof(short); i += 1) - bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte(); - return BitConverter.ToInt16(bytes, 0); - } - - private static int ReadLittleEndianInt32(BinaryReader binaryReader) - { - byte[] bytes = new byte[sizeof(int)]; - for (int i = 0; i < sizeof(int); i += 1) - bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte(); - return BitConverter.ToInt32(bytes, 0); - } - - private static Size? DecodeBitmap(BinaryReader binaryReader) - { - _ = binaryReader.ReadBytes(16); - int width = binaryReader.ReadInt32(); - int height = binaryReader.ReadInt32(); - return new Size(width, height); - } - - private static Size? DecodeGif(BinaryReader binaryReader) - { - int width = binaryReader.ReadInt16(); - int height = binaryReader.ReadInt16(); - return new Size(width, height); - } - - private static Size? DecodePng(BinaryReader binaryReader) - { - _ = binaryReader.ReadBytes(8); - int width = ReadLittleEndianInt32(binaryReader); - int height = ReadLittleEndianInt32(binaryReader); - return new Size(width, height); - } - - private static Size? DecodeJfif(BinaryReader binaryReader) - { - while (binaryReader.ReadByte() == 0xff) - { - byte marker = binaryReader.ReadByte(); - short chunkLength = ReadLittleEndianInt16(binaryReader); - if (marker == 0xc0) - { - _ = binaryReader.ReadByte(); - int height = ReadLittleEndianInt16(binaryReader); - int width = ReadLittleEndianInt16(binaryReader); - return new Size(width, height); - } - if (chunkLength >= 0) - _ = binaryReader.ReadBytes(chunkLength - 2); - else - { - ushort uChunkLength = (ushort)chunkLength; - _ = binaryReader.ReadBytes(uChunkLength - 2); - } - } - return null; - } - - private static Size? DecodeWebP(BinaryReader binaryReader) - { - _ = binaryReader.ReadUInt32(); // Size - _ = binaryReader.ReadBytes(15); // WEBP, VP8 + more - _ = binaryReader.ReadBytes(3); // SYNC - int width = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits width - int height = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits height - return new Size(width, height); - } - - internal static Size? GetDimensions(BinaryReader binaryReader) - { - int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length; - byte[] magicBytes = new byte[maxMagicBytesLength]; - for (int i = 0; i < maxMagicBytesLength; i += 1) - { - magicBytes[i] = binaryReader.ReadByte(); - foreach (KeyValuePair> kvPair in _ImageFormatDecoders) - { - if (StartsWith(magicBytes, kvPair.Key)) - return kvPair.Value(binaryReader); - } - } - return null; - } - - internal static Size? GetDimensions(string path) - { - using BinaryReader binaryReader = new(File.OpenRead(path)); - return GetDimensions(binaryReader); - } - -} \ No newline at end of file diff --git a/Helpers/Exif/Exif.cs b/Helpers/Exif/Exif.cs deleted file mode 100644 index f19c835..0000000 --- a/Helpers/Exif/Exif.cs +++ /dev/null @@ -1,534 +0,0 @@ -using MetadataExtractor; -using MetadataExtractor.Formats.Exif; -using MetadataExtractor.Formats.Exif.Makernotes; -using System.Globalization; - -namespace File_Folder_Helper.Helpers.Exif; - -internal abstract class Exif -{ - - private static DateTime? GetDateTime(string? value) - { - DateTime? result; - string dateTimeFormat = "yyyy:MM:dd HH:mm:ss"; - 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 Models.Exif.AviDirectory[] GetAviDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable aviDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.Avi.AviDirectory aviDirectory in aviDirectories) - { - if (aviDirectory.Tags.Count == 0) - continue; - DateTime? dateTimeOriginal; - string? duration = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagDuration); - string? height = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagHeight); - string? width = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagWidth); - if (aviDirectory.TryGetDateTime(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal, out DateTime checkDateTime)) - dateTimeOriginal = checkDateTime; - else - dateTimeOriginal = GetDateTime(aviDirectory.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal)); - if (dateTimeOriginal is null && duration is null && height is null && width is null) - continue; - results.Add(new(dateTimeOriginal, duration, height, width)); - } - return results.ToArray(); - } - - private static Models.Exif.ExifDirectoryBase[] GetExifBaseDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable exifBaseDirectories = directories.OfType(); - foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories) - { - if (exifDirectoryBase.Tags.Count == 0) - continue; - DateTime? dateTime; - DateTime checkDateTime; - DateTime? dateTimeOriginal; - DateTime? dateTimeDigitized; - string? aperture = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagAperture); - string? applicationNotes = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagApplicationNotes); - string? artist = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagArtist); - string? bitsPerSample = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBitsPerSample); - string? bodySerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBodySerialNumber); - string? cameraOwnerName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCameraOwnerName); - string? compressedAverageBitsPerPixel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompressedAverageBitsPerPixel); - string? compression = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompression); - string? copyright = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCopyright); - string? documentName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagDocumentName); - string? exifVersion = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExifVersion); - string? exposureTime = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExposureTime); - string? fileSource = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagFileSource); - string? imageDescription = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageDescription); - string? imageHeight = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageHeight); - string? imageNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageNumber); - string? imageUniqueId = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageUniqueId); - string? imageWidth = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageWidth); - string? isoSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagIsoSpeed); - string? lensMake = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensMake); - string? lensModel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensModel); - string? lensSerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensSerialNumber); - string? make = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMake); - string? makerNote = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMakernote); - string? model = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagModel); - string? orientation = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagOrientation); - int? orientationValue = orientation is null ? null : exifDirectoryBase.GetInt32(ExifDirectoryBase.TagOrientation); - string? rating = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRating); - string? ratingPercent = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRatingPercent); - string? securityClassification = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSecurityClassification); - string? shutterSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagShutterSpeed); - string? software = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSoftware); - string? timeZone = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZone); - string? timeZoneDigitized = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneDigitized); - string? timeZoneOriginal = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneOriginal); - string? userComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagUserComment); - string? winAuthor = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinAuthor); - string? winComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinComment); - string? winKeywords = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinKeywords); - string? winSubject = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinSubject); - string? winTitle = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinTitle); - string? xResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagXResolution); - string? yResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagYResolution); - if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime)) - dateTime = checkDateTime; - else - dateTime = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTime)); - if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime)) - dateTimeOriginal = checkDateTime; - else - dateTimeOriginal = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeOriginal)); - if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime)) - dateTimeDigitized = checkDateTime; - else - dateTimeDigitized = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeDigitized)); - if (userComment is not null && userComment.Length > 255) - userComment = "..."; - if (aperture is null - && applicationNotes is null - && artist is null - && bitsPerSample is null - && bodySerialNumber is null - && cameraOwnerName is null - && compressedAverageBitsPerPixel is null - && compression is null - && copyright is null - && dateTime is null - && dateTimeDigitized is null - && dateTimeOriginal is null - && documentName is null - && exifVersion is null - && exposureTime is null - && fileSource is null - && imageDescription is null - && imageHeight is null - && imageNumber is null - && imageUniqueId is null - && imageWidth is null - && isoSpeed is null - && lensMake is null - && lensModel is null - && lensSerialNumber is null - && make is null - && makerNote is null - && model is null - && orientation is null - && orientationValue is null - && rating is null - && ratingPercent is null - && securityClassification is null - && shutterSpeed is null - && software is null - && timeZone is null - && timeZoneDigitized is null - && timeZoneOriginal is null - && userComment is null - && winAuthor is null - && winComment is null - && winKeywords is null - && winSubject is null - && winTitle is null - && xResolution is not null - && yResolution is null) - continue; - results.Add(new(aperture, - applicationNotes, - artist, - bitsPerSample, - bodySerialNumber, - cameraOwnerName, - compressedAverageBitsPerPixel, - compression, - copyright, - dateTime, - dateTimeDigitized, - dateTimeOriginal, - documentName, - exifVersion, - exposureTime, - fileSource, - imageDescription, - imageHeight, - imageNumber, - imageUniqueId, - imageWidth, - isoSpeed, - lensMake, - lensModel, - lensSerialNumber, - make, - makerNote, - model, - orientation, - orientationValue, - rating, - ratingPercent, - securityClassification, - shutterSpeed, - software, - timeZone, - timeZoneDigitized, - timeZoneOriginal, - userComment, - winAuthor, - winComment, - winKeywords, - winSubject, - winTitle, - xResolution, - yResolution)); - } - return results.ToArray(); - } - - private static Models.Exif.FileMetadataDirectory[] GetFileMetadataDirectories(string file, IReadOnlyList directories) - { - List results = []; - IEnumerable fileMetadataDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.FileSystem.FileMetadataDirectory fileMetadataDirectory in fileMetadataDirectories) - { - if (fileMetadataDirectory.Tags.Count == 0) - continue; - DateTime? fileModifiedDate; - string? fileName = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileName); - string? fileSize = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileSize); - if (fileMetadataDirectory.TryGetDateTime(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate, out DateTime checkDateTime)) - fileModifiedDate = checkDateTime; - else - fileModifiedDate = GetDateTime(fileMetadataDirectory.GetString(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate)); - if (fileName is null || !file.EndsWith(fileName)) - throw new NotSupportedException($"!{file}.EndsWith({fileName})"); - if (fileModifiedDate is null && fileName is null && fileSize is null) - continue; - results.Add(new(fileModifiedDate, fileName, fileSize)); - } - return results.ToArray(); - } - - private static Models.Exif.GifHeaderDirectory[] GetGifHeaderDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable gifHeaderDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.Gif.GifHeaderDirectory gifHeaderDirectory in gifHeaderDirectories) - { - if (gifHeaderDirectory.Tags.Count == 0) - continue; - string? imageHeight = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageHeight); - string? imageWidth = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth); - if (imageHeight is null && imageWidth is null) - continue; - results.Add(new(imageHeight, imageWidth)); - } - return results.ToArray(); - } - - private static Models.Exif.GpsDirectory[] GetGpsDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable gpsDirectories = directories.OfType(); - foreach (GpsDirectory gpsDirectory in gpsDirectories) - { - if (gpsDirectory.Tags.Count == 0) - continue; - DateTime? timeStamp; - string? altitude = gpsDirectory.GetDescription(GpsDirectory.TagAltitude); - string? latitude = gpsDirectory.GetDescription(GpsDirectory.TagLatitude); - string? latitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLatitudeRef); - string? longitude = gpsDirectory.GetDescription(GpsDirectory.TagLongitude); - string? longitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLongitudeRef); - if (gpsDirectory.TryGetDateTime(GpsDirectory.TagTimeStamp, out DateTime checkDateTime)) - timeStamp = checkDateTime; - else - timeStamp = GetDateTime(gpsDirectory.GetString(GpsDirectory.TagTimeStamp)); - if (altitude is null && latitude is null && latitudeRef is null && longitude is null && longitudeRef is null && timeStamp is null) - continue; - results.Add(new(altitude, - latitude, - latitudeRef, - longitude, - longitudeRef, - timeStamp)); - } - return results.ToArray(); - } - - private static Models.Exif.JpegDirectory[] GetJpegDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable jpegDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.Jpeg.JpegDirectory jpegDirectory in jpegDirectories) - { - if (jpegDirectory.Tags.Count == 0) - continue; - string? imageHeight = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageHeight); - string? imageWidth = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth); - if (imageHeight is null && imageWidth is null) - continue; - results.Add(new(imageHeight, imageWidth)); - } - return results.ToArray(); - } - - private static Models.Exif.MakernoteDirectory[] GetMakernoteDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable appleMakernoteDirectories = directories.OfType(); - foreach (AppleMakernoteDirectory appleMakernoteDirectory in appleMakernoteDirectories) - { - if (appleMakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = null; - string? firmwareVersion = null; - string? qualityAndFileFormat = null; - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable canonMakernoteDirectories = directories.OfType(); - foreach (CanonMakernoteDirectory canonMakernoteDirectory in canonMakernoteDirectories) - { - if (canonMakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagModelId); - string? firmwareVersion = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagCanonFirmwareVersion); - string? qualityAndFileFormat = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.CameraSettings.TagQuality); - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable nikonType2MakernoteDirectories = directories.OfType(); - foreach (NikonType2MakernoteDirectory nikonType2MakernoteDirectory in nikonType2MakernoteDirectories) - { - if (nikonType2MakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagCameraSerialNumber); - string? firmwareVersion = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagFirmwareVersion); - string? qualityAndFileFormat = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagQualityAndFileFormat); - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable olympusMakernoteDirectories = directories.OfType(); - foreach (OlympusMakernoteDirectory olympusMakernoteDirectory in olympusMakernoteDirectories) - { - if (olympusMakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagSerialNumber1); - string? firmwareVersion = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagBodyFirmwareVersion); - string? qualityAndFileFormat = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagJpegQuality); - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable panasonicMakernoteDirectories = directories.OfType(); - foreach (PanasonicMakernoteDirectory panasonicMakernoteDirectory in panasonicMakernoteDirectories) - { - if (panasonicMakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagInternalSerialNumber); - string? firmwareVersion = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagFirmwareVersion); - string? qualityAndFileFormat = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagQualityMode); - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable samsungType2MakernoteDirectories = directories.OfType(); - foreach (SamsungType2MakernoteDirectory samsungType2MakernoteDirectory in samsungType2MakernoteDirectories) - { - if (samsungType2MakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagSerialNumber); - string? firmwareVersion = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagFirmwareName); - string? qualityAndFileFormat = null; - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - IEnumerable sonyType6MakernoteDirectories = directories.OfType(); - foreach (SonyType6MakernoteDirectory sonyType6MakernoteDirectory in sonyType6MakernoteDirectories) - { - if (sonyType6MakernoteDirectory.Tags.Count == 0) - continue; - string? cameraSerialNumber = null; - string? firmwareVersion = null; - string? qualityAndFileFormat = null; - if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null) - continue; - results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat)); - } - return results.ToArray(); - } - - private static Models.Exif.PhotoshopDirectory[] GetPhotoshopDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable photoshopDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.Photoshop.PhotoshopDirectory photoshopDirectory in photoshopDirectories) - { - if (photoshopDirectory.Tags.Count == 0) - continue; - string? jpegQuality = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagJpegQuality); - string? url = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl); - if (jpegQuality is null && url is null) - continue; - results.Add(new(jpegQuality, url)); - } - return results.ToArray(); - } - - private static Models.Exif.PngDirectory[] GetPngDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable pngDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.Png.PngDirectory pngDirectory in pngDirectories) - { - if (pngDirectory.Tags.Count == 0) - continue; - string? imageHeight = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageHeight); - string? imageWidth = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageWidth); - string? textualData = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagTextualData); - if (imageHeight is null && imageWidth is null && textualData is null) - continue; - results.Add(new(imageHeight, imageWidth, textualData)); - } - return results.ToArray(); - } - - private static Models.Exif.QuickTimeMovieHeaderDirectory[] GetQuickTimeMovieHeaderDirectoryDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable quickTimeMovieHeaderDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory in quickTimeMovieHeaderDirectories) - { - if (quickTimeMovieHeaderDirectory.Tags.Count == 0) - continue; - DateTime? created; - if (quickTimeMovieHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated, out DateTime checkDateTime)) - created = checkDateTime; - else - created = GetDateTime(quickTimeMovieHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated)); - if (created is null) - continue; - results.Add(new(created)); - } - return results.ToArray(); - } - - private static Models.Exif.QuickTimeTrackHeaderDirectory[] GetQuickTimeTrackHeaderDirectoryDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable quickTimeTrackHeaderDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory in quickTimeTrackHeaderDirectories) - { - if (quickTimeTrackHeaderDirectory.Tags.Count == 0) - continue; - DateTime? created; - if (quickTimeTrackHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated, out DateTime checkDateTime)) - created = checkDateTime; - else - created = GetDateTime(quickTimeTrackHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated)); - if (created is null) - continue; - results.Add(new(created)); - } - return results.ToArray(); - } - - private static Models.Exif.WebPDirectory[] GetWebPDirectories(IReadOnlyList directories) - { - List results = []; - IEnumerable webPDirectories = directories.OfType(); - foreach (MetadataExtractor.Formats.WebP.WebPDirectory webPDirectory in webPDirectories) - { - if (webPDirectory.Tags.Count == 0) - continue; - string? imageHeight = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageHeight); - string? imageWidth = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth); - if (imageHeight is null && imageWidth is null) - continue; - results.Add(new(imageHeight, imageWidth)); - } - return results.ToArray(); - } - - private static Models.Exif.ExifDirectory Covert(FileInfo fileInfo, System.Drawing.Size? size, int id, IReadOnlyList directories) - { - Models.Exif.ExifDirectory result; - Models.Exif.AviDirectory[] aviDirectories = GetAviDirectories(directories); - Models.Exif.GpsDirectory[] gpsDirectories = GetGpsDirectories(directories); - Models.Exif.PngDirectory[] pngDirectories = GetPngDirectories(directories); - Models.Exif.JpegDirectory[] jpegDirectories = GetJpegDirectories(directories); - Models.Exif.WebPDirectory[] webPDirectories = GetWebPDirectories(directories); - Models.Exif.ExifDirectoryBase[] exifBaseDirectories = GetExifBaseDirectories(directories); - Models.Exif.GifHeaderDirectory[] gifHeaderDirectories = GetGifHeaderDirectories(directories); - Models.Exif.MakernoteDirectory[] MakernoteDirectories = GetMakernoteDirectories(directories); - Models.Exif.PhotoshopDirectory[] photoshopDirectories = GetPhotoshopDirectories(directories); - Models.Exif.FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(fileInfo.FullName, directories); - Models.Exif.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories); - Models.Exif.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories); - result = new(aviDirectories, - exifBaseDirectories, - fileMetadataDirectories, - gifHeaderDirectories, - gpsDirectories, - size?.Height, - id, - jpegDirectories, - MakernoteDirectories, - fileInfo.Name, - photoshopDirectories, - pngDirectories, - quickTimeMovieHeaderDirectories, - quickTimeTrackHeaderDirectories, - webPDirectories, - size?.Width); - return result; - } - - internal static Models.Exif.ExifDirectory GetExifDirectory(FileInfo fileInfo) - { - Models.Exif.ExifDirectory result; - int id = 1; - System.Drawing.Size? size; - try - { size = Dimensions.GetDimensions(fileInfo.FullName); } - catch (Exception) - { size = null; } - IReadOnlyList directories = ImageMetadataReader.ReadMetadata(fileInfo.FullName); - result = Covert(fileInfo, size, id, directories); - return result; - } - -} \ No newline at end of file diff --git a/Helpers/Exif/HelperExif.cs b/Helpers/Exif/HelperExif.cs deleted file mode 100644 index a128666..0000000 --- a/Helpers/Exif/HelperExif.cs +++ /dev/null @@ -1,55 +0,0 @@ -using File_Folder_Helper.Models; -using File_Folder_Helper.Models.Exif; -using File_Folder_Helper.Models.Face; -using Microsoft.Extensions.Logging; -using System.Collections.ObjectModel; -using System.Text.Json; - -namespace File_Folder_Helper.Helpers.Exif; - -internal static class HelperExif -{ - - private static ReadOnlyCollection GetCollection(ExifDirectoryBase[]? exifDirectoryBases) - { - List results = []; - if (exifDirectoryBases is not null) - { - string? json; - FaceFile[]? collection; - foreach (ExifDirectoryBase exifDirectoryBase in exifDirectoryBases) - { - json = exifDirectoryBase.Artist; - if (string.IsNullOrEmpty(json)) - continue; - collection = JsonSerializer.Deserialize(json, FaceFileCollectionGenerationContext.Default.FaceFileArray); - if (collection is null) - continue; - results.AddRange(collection); - } - } - return new(results); - } - - internal static void DragAndDrop(ILogger logger, string argZero) - { - FileInfo fileInfo = new(argZero); - logger.LogInformation("<{argZero}> exists", argZero); - ExifDirectory exifDirectory = Exif.GetExifDirectory(fileInfo); - string directory = Path.GetDirectoryName(argZero) ?? throw new Exception(); - string[] files = Directory.GetFiles(directory, "*.json", SearchOption.TopDirectoryOnly); - string? json = files.Length != 1 ? string.Empty : File.ReadAllText(files[0]); - ReadOnlyCollection collection = GetCollection(exifDirectory.ExifBaseDirectories); - logger.LogInformation("<{collection}> value", collection.Count); - Dictionary? people = string.IsNullOrEmpty(json) ? [] : JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException(); - logger.LogInformation("<{people}> value", people?.Count); - foreach (FaceFile faceFile in collection) - { - if (faceFile.MappingFromPerson is null) - logger.LogInformation("<{Confidence}> value", faceFile.Location?.Confidence); - else - logger.LogInformation("<{DisplayDirectoryName}> value", faceFile.MappingFromPerson.DisplayDirectoryName); - } - } - -} \ No newline at end of file diff --git a/Helpers/ExifHelper.cs b/Helpers/ExifHelper.cs new file mode 100644 index 0000000..f2672ab --- /dev/null +++ b/Helpers/ExifHelper.cs @@ -0,0 +1,43 @@ +using File_Folder_Helper.Models; +using Microsoft.Extensions.Logging; +using System.Text.Json; +using Phares.Metadata.Models.Stateless; +using Phares.Shared.Models; + +namespace File_Folder_Helper.Helpers; + +internal static partial class ExifHelper +{ + + internal static void DragAndDrop(ILogger logger, string argZero) + { + string? json; + string secrets = "L:/Git/AA/Rename/.vscode/.UserSecrets/secrets.json"; + json = !File.Exists(secrets) ? null : File.ReadAllText(secrets); + if (string.IsNullOrEmpty(json)) + throw new Exception($"Use mklink to map user secrets for rename!"); + ResultSettings? resultSettings = JsonSerializer.Deserialize(json, ResultSettingsSourceGenerationContext.Default.ResultSettings) ?? + throw new Exception(nameof(ResultSettings)); + MetadataSettings? metadataSettings = JsonSerializer.Deserialize(json, MetadataSettingsSourceGenerationContext.Default.MetadataSettings) ?? + throw new Exception(nameof(MetadataSettings)); + FileInfo fileInfo = new(argZero); + logger.LogInformation("<{argZero}> exists", argZero); + if (!string.IsNullOrEmpty(fileInfo.Directory?.FullName)) + { + string[] files = Directory.GetFiles(fileInfo.Directory.FullName, "*.json", SearchOption.TopDirectoryOnly); + json = files.Length != 1 ? string.Empty : File.ReadAllText(files[0]); + Dictionary? people = string.IsNullOrEmpty(json) ? [] : JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException(); + logger.LogInformation("<{people}> value", people?.Count); + } + ExifDirectory? exifDirectory = IMetadata.GetExifDirectory(resultSettings, metadataSettings, fileInfo); + FaceFile? faceFile = IMetadata.GetFaceFile(exifDirectory); + if (faceFile is not null) + { + if (faceFile.MappingFromPerson is null) + logger.LogInformation("<{Confidence}> value", faceFile.Location?.Confidence); + else + logger.LogInformation("<{DisplayDirectoryName}> value", faceFile.MappingFromPerson.DisplayDirectoryName); + } + } + +} \ No newline at end of file diff --git a/Models/Exif/AviDirectory.cs b/Models/Exif/AviDirectory.cs deleted file mode 100644 index a275b9f..0000000 --- a/Models/Exif/AviDirectory.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record AviDirectory(DateTime? DateTimeOriginal, - string? Duration, - string? Height, - string? Width) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, AviDirectorySourceGenerationContext.Default.AviDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(AviDirectory))] -public partial class AviDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/ExifDirectory.cs b/Models/Exif/ExifDirectory.cs deleted file mode 100644 index 0e678ed..0000000 --- a/Models/Exif/ExifDirectory.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record ExifDirectory(AviDirectory[] AviDirectories, - ExifDirectoryBase[] ExifBaseDirectories, - FileMetadataDirectory[] FileMetadataDirectories, - GifHeaderDirectory[] GifHeaderDirectories, - GpsDirectory[] GpsDirectories, - int? Height, - int? Id, - JpegDirectory[] JpegDirectories, - MakernoteDirectory[] MakernoteDirectories, - string OriginalFileName, - PhotoshopDirectory[] PhotoshopDirectories, - PngDirectory[] PngDirectories, - QuickTimeMovieHeaderDirectory[] QuickTimeMovieHeaderDirectories, - QuickTimeTrackHeaderDirectory[] QuickTimeTrackHeaderDirectories, - WebPDirectory[] WebPDirectories, - int? Width) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, ExifDirectorySourceGenerationContext.Default.ExifDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] -[JsonSerializable(typeof(ExifDirectory))] -public partial class ExifDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/ExifDirectoryBase.cs b/Models/Exif/ExifDirectoryBase.cs deleted file mode 100644 index 935291a..0000000 --- a/Models/Exif/ExifDirectoryBase.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record ExifDirectoryBase(string? Aperture, - string? ApplicationNotes, - string? Artist, - string? BitsPerSample, - string? BodySerialNumber, - string? CameraOwnerName, - string? CompressedAverageBitsPerPixel, - string? Compression, - string? Copyright, - DateTime? DateTime, - DateTime? DateTimeDigitized, - DateTime? DateTimeOriginal, - string? DocumentName, - string? ExifVersion, - string? ExposureTime, - string? FileSource, - string? ImageDescription, - string? ImageHeight, - string? ImageNumber, - string? ImageUniqueId, - string? ImageWidth, - string? IsoSpeed, - string? LensMake, - string? LensModel, - string? LensSerialNumber, - string? Make, - string? MakerNote, - string? Model, - string? Orientation, - int? OrientationValue, - string? Rating, - string? RatingPercent, - string? SecurityClassification, - string? ShutterSpeed, - string? Software, - string? TimeZone, - string? TimeZoneDigitized, - string? TimeZoneOriginal, - string? UserComment, - string? WinAuthor, - string? WinComment, - string? WinKeywords, - string? WinSubject, - string? WinTitle, - string? XResolution, - string? YResolution) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(ExifDirectoryBase))] -public partial class ExifDirectoryBaseSourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/FileMetadataDirectory.cs b/Models/Exif/FileMetadataDirectory.cs deleted file mode 100644 index c971390..0000000 --- a/Models/Exif/FileMetadataDirectory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record FileMetadataDirectory(DateTime? FileModifiedDate, - string? FileName, - string? FileSize) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, FileMetadataDirectorySourceGenerationContext.Default.FileMetadataDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(FileMetadataDirectory))] -public partial class FileMetadataDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/GifHeaderDirectory.cs b/Models/Exif/GifHeaderDirectory.cs deleted file mode 100644 index b8fc7b8..0000000 --- a/Models/Exif/GifHeaderDirectory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record GifHeaderDirectory(string? ImageHeight, - string? ImageWidth) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, GifHeaderDirectorySourceGenerationContext.Default.GifHeaderDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(GifHeaderDirectory))] -public partial class GifHeaderDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/GpsDirectory.cs b/Models/Exif/GpsDirectory.cs deleted file mode 100644 index 02bf8b2..0000000 --- a/Models/Exif/GpsDirectory.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record GpsDirectory(string? Altitude, - string? Latitude, - string? LatitudeRef, - string? Longitude, - string? LongitudeRef, - DateTime? TimeStamp) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, GpsDirectorySourceGenerationContext.Default.GpsDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(GpsDirectory))] -public partial class GpsDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/JpegDirectory.cs b/Models/Exif/JpegDirectory.cs deleted file mode 100644 index 43d8a14..0000000 --- a/Models/Exif/JpegDirectory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record JpegDirectory(string? ImageHeight, - string? ImageWidth) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, JpegDirectorySourceGenerationContext.Default.JpegDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(JpegDirectory))] -public partial class JpegDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/MakernoteDirectory.cs b/Models/Exif/MakernoteDirectory.cs deleted file mode 100644 index 7304b10..0000000 --- a/Models/Exif/MakernoteDirectory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record MakernoteDirectory(string? CameraSerialNumber, - string? FirmwareVersion, - string? QualityAndFileFormat) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, MakernoteDirectorySourceGenerationContext.Default.MakernoteDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(MakernoteDirectory))] -public partial class MakernoteDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/PhotoshopDirectory.cs b/Models/Exif/PhotoshopDirectory.cs deleted file mode 100644 index 37c68e7..0000000 --- a/Models/Exif/PhotoshopDirectory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record PhotoshopDirectory(string? JpegQuality, - string? Url) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, PhotoshopDirectorySourceGenerationContext.Default.PhotoshopDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(PhotoshopDirectory))] -public partial class PhotoshopDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/PngDirectory.cs b/Models/Exif/PngDirectory.cs deleted file mode 100644 index 8af281a..0000000 --- a/Models/Exif/PngDirectory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record PngDirectory(string? ImageHeight, - string? ImageWidth, - string? TextualData) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, PngDirectorySourceGenerationContext.Default.PngDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(PngDirectory))] -public partial class PngDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/QuickTimeMovieHeaderDirectory.cs b/Models/Exif/QuickTimeMovieHeaderDirectory.cs deleted file mode 100644 index d8da238..0000000 --- a/Models/Exif/QuickTimeMovieHeaderDirectory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record QuickTimeMovieHeaderDirectory(DateTime? Created) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, QuickTimeMovieHeaderDirectorySourceGenerationContext.Default.QuickTimeMovieHeaderDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(QuickTimeMovieHeaderDirectory))] -public partial class QuickTimeMovieHeaderDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/QuickTimeTrackHeaderDirectory.cs b/Models/Exif/QuickTimeTrackHeaderDirectory.cs deleted file mode 100644 index 230dc3f..0000000 --- a/Models/Exif/QuickTimeTrackHeaderDirectory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record QuickTimeTrackHeaderDirectory(DateTime? Created) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, QuickTimeTrackHeaderDirectorySourceGenerationContext.Default.QuickTimeTrackHeaderDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(QuickTimeTrackHeaderDirectory))] -public partial class QuickTimeTrackHeaderDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Exif/WebPDirectory.cs b/Models/Exif/WebPDirectory.cs deleted file mode 100644 index 99873de..0000000 --- a/Models/Exif/WebPDirectory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Exif; - -public record WebPDirectory(string? ImageHeight, - string? ImageWidth) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, WebPDirectorySourceGenerationContext.Default.WebPDirectory); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(WebPDirectory))] -public partial class WebPDirectorySourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Face/FaceEncoding.cs b/Models/Face/FaceEncoding.cs deleted file mode 100644 index 7349861..0000000 --- a/Models/Face/FaceEncoding.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Face; - -public record FaceEncoding(double[] RawEncoding, int Size); - -[JsonSourceGenerationOptions(WriteIndented = false)] -[JsonSerializable(typeof(FaceEncoding))] -public partial class FaceEncodingGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Face/FaceFile.cs b/Models/Face/FaceFile.cs deleted file mode 100644 index c15801a..0000000 --- a/Models/Face/FaceFile.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Face; - -public record FaceFile(int? AreaPermyriad, - int? ConfidencePercent, - string? DMS, - DateTime DateTime, - FaceEncoding? FaceEncoding, - Dictionary? FaceParts, - Location? Location, - string? Maker, - MappingFromPerson? MappingFromPerson, - string? Model, - OutputResolution? OutputResolution); - -[JsonSourceGenerationOptions(WriteIndented = false)] -[JsonSerializable(typeof(FaceFile))] -public partial class FaceFileGenerationContext : JsonSerializerContext -{ -} - -[JsonSourceGenerationOptions(WriteIndented = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] -[JsonSerializable(typeof(FaceFile[]))] -public partial class FaceFileCollectionGenerationContext : JsonSerializerContext -{ -} - -[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] -[JsonSerializable(typeof(FaceFile[]))] -public partial class FaceFileCollectionWriteIndentedGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Face/FacePart.cs b/Models/Face/FacePart.cs deleted file mode 100644 index 26fb934..0000000 --- a/Models/Face/FacePart.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace File_Folder_Helper.Models.Face; - -/// -/// Specifies the part of face. -/// -public enum FacePart -{ - - /// - /// Specifies the chin. - /// - Chin = 0, - - /// - /// Specifies the left eyebrow. - /// - LeftEyebrow = 17, - - /// - /// Specifies the right eyebrow. - /// - RightEyebrow = 22, - - /// - /// Specifies the nose bridge. - /// - NoseBridge = 27, - - /// - /// Specifies the nose tip. - /// - NoseTip = 31, - - /// - /// Specifies the left eye. - /// - LeftEye = 36, - - /// - /// Specifies the right eye. - /// - RightEye = 42, - - /// - /// Specifies the top lip. - /// - TopLip = 48, - - /// - /// Specifies the bottom lip. - /// - BottomLip = 55 - -} \ No newline at end of file diff --git a/Models/Face/FacePoint.cs b/Models/Face/FacePoint.cs deleted file mode 100644 index 17d5ea6..0000000 --- a/Models/Face/FacePoint.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Drawing; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Face; - -[method: JsonConstructor] -public class FacePoint(int index, int x, int y) -{ - public int Index { get; } = index; - public int X { get; } = x; - public int Y { get; } = y; - - private readonly Point _Point = new(x, y); - - public override bool Equals(object? obj) => obj is FacePoint point && Equals(point); - -#pragma warning disable IDE0070 - public override int GetHashCode() -#pragma warning restore IDE0070 - { - int hashCode = 1861411795; - hashCode = (hashCode * -1521134295) + _Point.GetHashCode(); - hashCode = (hashCode * -1521134295) + Index.GetHashCode(); - return hashCode; - } - - public bool Equals(FacePoint? facePoint) - { - return facePoint is not null - && X == facePoint.X - && Y == facePoint.Y - && Index == facePoint.Index; - } - - public static bool operator ==(FacePoint point1, FacePoint point2) => point1.Equals(point2); - - public static bool operator !=(FacePoint point1, FacePoint point2) => !(point1 == point2); - -} \ No newline at end of file diff --git a/Models/Face/Location.cs b/Models/Face/Location.cs deleted file mode 100644 index 75570d2..0000000 --- a/Models/Face/Location.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Face; - -[method: JsonConstructor] -public class Location(int bottom, double confidence, int left, int right, int top) : IEquatable -{ - - public int Bottom { init; get; } = bottom; - public double Confidence { init; get; } = confidence; - public int Left { init; get; } = left; - public int Right { init; get; } = right; - public int Top { init; get; } = top; - - public override bool Equals(object? obj) => Equals(obj as Location); - -#pragma warning disable IDE0070 - public override int GetHashCode() -#pragma warning restore IDE0070 - { - int hashCode = -773114317; - hashCode = (hashCode * -1521134295) + Bottom.GetHashCode(); - hashCode = (hashCode * -1521134295) + Left.GetHashCode(); - hashCode = (hashCode * -1521134295) + Right.GetHashCode(); - hashCode = (hashCode * -1521134295) + Top.GetHashCode(); - return hashCode; - } - - public bool Equals(Location? location) - { - return location is not null - && Bottom == location.Bottom - && Left == location.Left - && Right == location.Right - && Top == location.Top; - } - - public static bool operator ==(Location location1, Location location2) => EqualityComparer.Default.Equals(location1, location2); - - public static bool operator !=(Location location1, Location location2) => !(location1 == location2); - -} \ No newline at end of file diff --git a/Models/Face/MappingFromPerson.cs b/Models/Face/MappingFromPerson.cs deleted file mode 100644 index 531c4e6..0000000 --- a/Models/Face/MappingFromPerson.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace File_Folder_Helper.Models.Face; - -public record MappingFromPerson(int? ApproximateYears, - string DisplayDirectoryName, - long PersonKey, - string SegmentB) -{ - - public override string ToString() - { - string result = JsonSerializer.Serialize(this, MappingFromPersonGenerationContext.Default.MappingFromPerson); - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(MappingFromPerson))] -public partial class MappingFromPersonGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Models/Face/OutputResolution.cs b/Models/Face/OutputResolution.cs deleted file mode 100644 index 204ef80..0000000 --- a/Models/Face/OutputResolution.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace File_Folder_Helper.Models.Face; - -public record OutputResolution(int Height, - int Orientation, - int Width); \ No newline at end of file diff --git a/Worker.cs b/Worker.cs index 3fbbfd2..65c0f54 100644 --- a/Worker.cs +++ b/Worker.cs @@ -235,7 +235,7 @@ public class Worker : BackgroundService } } else if (_AppSettings.ValidImageFormatExtensions.Contains(extension) && File.Exists(_Args[0])) - Helpers.Exif.HelperExif.DragAndDrop(_Logger, _Args[0]); + Helpers.ExifHelper.DragAndDrop(_Logger, _Args[0]); else throw new Exception(_Args[0]); }