person-key-to-immich-import birthday json (Day-Helper-2024-05-18)

csharp_prefer_braces = true
This commit is contained in:
2025-09-06 11:16:55 -07:00
parent 8ec89953bc
commit 6102da7266
54 changed files with 2218 additions and 1721 deletions

View File

@ -17,6 +17,67 @@ internal static partial class Helper20250720 {
private partial class Helper20250720SettingsSourceGenerationContext : JsonSerializerContext {
}
private static void WriteFaceData(ILogger<Worker> logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection<ExifDirectory> exifDirectories, ReadOnlyCollection<string> digiKamFiles) {
ReadOnlyDictionary<string, FaceFile> keyValuePairs = GetKeyValuePairs(logger, exifDirectories);
if (keyValuePairs.Count > 0) {
WriteFaceData(logger, outputDirectoryName, originalFile, fileNameFirstSegment, digiKamFiles, keyValuePairs);
}
}
private static void WriteFaceData(ILogger<Worker> logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection<string> digiKamFiles, ReadOnlyDictionary<string, FaceFile> 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/\"",
"</rdf:RDF>"
];
foreach (string digiKamFile in digiKamFiles) {
string[] lines = File.ReadAllLines(digiKamFile);
List<string> 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);
}
}
}
}
internal static void WriteFaceData(ILogger<Worker> logger, List<string> args) {
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
@ -84,24 +145,6 @@ internal static partial class Helper20250720 {
}
}
private static void WriteFaceData(ILogger<Worker> logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection<ExifDirectory> exifDirectories, ReadOnlyCollection<string> digiKamFiles) {
ReadOnlyDictionary<string, FaceFile> keyValuePairs = GetKeyValuePairs(logger, exifDirectories);
if (keyValuePairs.Count > 0) {
WriteFaceData(logger, outputDirectoryName, originalFile, fileNameFirstSegment, digiKamFiles, keyValuePairs);
}
}
private static int? GetMatchingLine(string digiKamLine, ReadOnlyCollection<string> 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<string, FaceFile> keyValuePairs, string digiKamFile, List<string> trimmed, int rdfLine) {
if (keyValuePairs.Count == 0) {
throw new Exception();
@ -118,8 +161,9 @@ internal static partial class Helper20250720 {
FaceFile faceFile;
string descriptionLine = "</rdf:Description>";
faceFile = keyValuePairs.ElementAt(0).Value;
if (faceFile.Location is null || faceFile.OutputResolution is null)
if (faceFile.Location is null || faceFile.OutputResolution is null) {
throw new Exception();
}
List<string> regionLines = [
"<MP:RegionInfo rdf:parseType=\"Resource\">",
"<MPRI:Regions>",
@ -142,8 +186,9 @@ internal static partial class Helper20250720 {
foreach (KeyValuePair<string, FaceFile> keyValuePair in keyValuePairs) {
personKey = keyValuePair.Key;
faceFile = keyValuePair.Value;
if (faceFile.Location is null || faceFile.OutputResolution is null)
if (faceFile.Location is null || faceFile.OutputResolution is null) {
throw new Exception();
}
width = faceFile.Location.Right - faceFile.Location.Left;
height = faceFile.Location.Bottom - faceFile.Location.Top;
if (!string.IsNullOrEmpty(originalFile) && File.Exists(originalFile)) {
@ -156,8 +201,9 @@ internal static partial class Helper20250720 {
}
w = width / faceFile.OutputResolution.Width;
h = height / faceFile.OutputResolution.Height;
if (w == 0 || h == 0)
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;
@ -338,12 +384,14 @@ internal static partial class Helper20250720 {
continue;
}
exifDirectory = IMetadata.GetExifDirectory(resultSettings, metadataSettings, faceFileInfo);
if (exifDirectory is null)
if (exifDirectory is null) {
continue;
}
if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) {
keyValuePairs.Add(fileNameFirstSegment, []);
if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection))
if (!keyValuePairs.TryGetValue(fileNameFirstSegment, out collection)) {
throw new Exception();
}
}
collection.Add(exifDirectory);
}
@ -365,58 +413,15 @@ internal static partial class Helper20250720 {
}
}
private static void WriteFaceData(ILogger<Worker> logger, string outputDirectoryName, string? originalFile, long? fileNameFirstSegment, ReadOnlyCollection<string> digiKamFiles, ReadOnlyDictionary<string, FaceFile> 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/\"",
"</rdf:RDF>"
];
foreach (string digiKamFile in digiKamFiles) {
string[] lines = File.ReadAllLines(digiKamFile);
List<string> 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 int? GetMatchingLine(string digiKamLine, ReadOnlyCollection<string> lines) {
int? result = null;
for (int i = 0; i < lines.Count; i++) {
if (lines[i] == digiKamLine) {
result = i;
break;
}
}
return result;
}
private static void Extract(string file, double width, double height, int left, int top, string suffix) {