Mike Phares 8863fd763f Removed old GetRectangle
RectangleIntersectMinimums
AddUserSecrets
2023-06-19 21:33:04 -07:00

251 lines
12 KiB
C#

using System.Text;
using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.PhotoPrism.Models;
public class F_PhotoPrism
{
private static JsonProperty[] GetJsonProperty(string fileName)
{
JsonProperty[] results;
if (!File.Exists(fileName))
results = Array.Empty<JsonProperty>();
else
{
string json = File.ReadAllText(fileName);
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json);
if (jsonElements is null || !jsonElements.Any())
results = Array.Empty<JsonProperty>();
else
{
JsonElement jsonElement = jsonElements.Last();
if (jsonElement.ValueKind != JsonValueKind.Object)
results = Array.Empty<JsonProperty>();
else
results = jsonElement.EnumerateObject().ToArray();
}
}
return results;
}
private static Marker[]? GetMarkers(string fPhotoPrismSingletonDirectory)
{
Marker[]? results;
string file = Path.Combine(fPhotoPrismSingletonDirectory, "markers.json");
JsonProperty[] jsonProperties = GetJsonProperty(file);
if (!jsonProperties.Any())
results = null;
else
results = JsonSerializer.Deserialize<Marker[]>(jsonProperties.Last().Value);
return results;
}
private static Dictionary<string, List<Shared.Models.Marker>> GetFileUIdToMarkers(string fPhotoPrismSingletonDirectory)
{
Dictionary<string, List<Shared.Models.Marker>> results = new();
string fileUid;
Marker[]? markers = GetMarkers(fPhotoPrismSingletonDirectory);
if (markers is null)
throw new NullReferenceException(nameof(markers));
foreach (Marker marker in markers)
{
fileUid = HexStringToString(marker.FileUid);
if (!results.ContainsKey(fileUid))
results.Add(fileUid, new());
results[fileUid].Add(Marker.Map(marker));
}
return results;
}
private static Dictionary<int, List<MappingFromPhotoPrism>>? GetCollectionFile(string fileName)
{
Dictionary<int, List<MappingFromPhotoPrism>>? results;
if (!File.Exists(fileName))
results = null;
else
{
string json = File.ReadAllText(fileName);
results = JsonSerializer.Deserialize<Dictionary<int, List<MappingFromPhotoPrism>>>(json);
}
return results;
}
private static List<Shared.Models.DatabaseFile>? GetDatabaseFiles(string fPhotoPrismSingletonDirectory)
{
List<Shared.Models.DatabaseFile>? results;
string file = Path.Combine(fPhotoPrismSingletonDirectory, "files.json");
JsonProperty[] jsonProperties = GetJsonProperty(file);
if (!jsonProperties.Any())
results = null;
else
{
results = new();
DatabaseFile[]? databaseFiles = JsonSerializer.Deserialize<DatabaseFile[]>(jsonProperties.Last().Value);
if (databaseFiles is null)
results = null;
else
{
foreach (DatabaseFile databaseFile in databaseFiles)
results.Add(DatabaseFile.Map(databaseFile));
}
}
return results;
}
public static Dictionary<int, List<MappingFromPhotoPrism>> GetFileNameToCollection(string fPhotoPrismSingletonDirectory)
{
Dictionary<int, List<MappingFromPhotoPrism>>? results;
string fileName = Path.Combine(fPhotoPrismSingletonDirectory, "collection.json");
results = GetCollectionFile(fileName);
if (results is null)
{
int id;
results = new();
string fileNameWithoutExtension;
List<Shared.Models.Marker>? makers;
MappingFromPhotoPrism mappingFromPhotoPrism;
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
List<Shared.Models.DatabaseFile>? databaseFiles = GetDatabaseFiles(fPhotoPrismSingletonDirectory);
if (databaseFiles is not null)
{
Dictionary<string, List<Shared.Models.Marker>> fileUIdToMarkers = GetFileUIdToMarkers(fPhotoPrismSingletonDirectory);
foreach (Shared.Models.DatabaseFile databaseFile in databaseFiles)
{
if (databaseFile.FileName is null || databaseFile.FileUid is null)
continue;
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(databaseFile.FileName);
if (!int.TryParse(fileNameWithoutExtension, out id))
continue;
if (!results.TryGetValue(id, out mappingFromPhotoPrismCollection))
{
results.Add(id, new());
if (!results.TryGetValue(id, out mappingFromPhotoPrismCollection))
throw new Exception();
}
if (!fileUIdToMarkers.TryGetValue(databaseFile.FileUid, out makers))
mappingFromPhotoPrism = new(databaseFile, new());
else
mappingFromPhotoPrism = new(databaseFile, makers);
mappingFromPhotoPrismCollection.Add(mappingFromPhotoPrism);
}
}
string json = JsonSerializer.Serialize(results);
_ = IPath.WriteAllText(fileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
return results;
}
private static void PopulateSubjects(string mappingDefaultName, string personBirthdayFormat, List<string> subjects, StringBuilder stringBuilder, PersonContainer[] personContainers, (MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection)
{
long? personKey;
string personName;
const int zero = 0;
string personKeyFormatted;
PersonBirthday personBirthday;
foreach ((MappingFromPhotoPrism mappingFromPhotoPrism, Shared.Models.Marker marker, double percent) in sortedCollection)
{
foreach (PersonContainer personContainer in personContainers)
{
if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || !personContainer.Birthdays.Any())
continue;
if (IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName) || IPerson.IsDefaultName(mappingDefaultName, personContainer.Person))
continue;
personBirthday = personContainer.Birthdays[zero];
personKey = personBirthday.Value.Ticks;
personName = personContainer.Person.GetFullName();
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
subjects.Add($"update `subjects` set subj_alias = '{personKeyFormatted}' where subj_name = '{personName}';");
_ = stringBuilder.
Append("update `markers` set subj_src = 'manual', marker_name = '").
Append(personName).
Append("' where marker_uid = '").
Append(marker.MarkerUid).
AppendLine("';");
}
}
}
public static void WriteMatches(string fPhotoPrismContentDirectory, string mappingDefaultName, string personBirthdayFormat, float[] rectangleIntersectMinimums, long ticks, List<Face> distinctFilteredFaces, Shared.Models.Methods.IMapLogic mapLogic)
{
string file;
string text;
double percent;
int? normalizedRectangle;
List<string> subjects = new();
PersonContainer[]? personContainers;
StringBuilder stringBuilder = new();
System.Drawing.Rectangle dlibRectangle;
System.Drawing.Rectangle? prismRectangle;
System.Drawing.Rectangle intersectRectangle;
float rectangleIntersectMinimum = rectangleIntersectMinimums.Min();
Dictionary<int, PersonContainer[]>? normalizedRectangleToPersonContainers;
(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)[] sortedCollection;
List<(MappingFromPhotoPrism MappingFromPhotoPrism, Shared.Models.Marker Marker, double Percent)> collection = new();
foreach (Face face in distinctFilteredFaces)
{
collection.Clear();
normalizedRectangle = face.Mapping?.MappingFromLocation?.NormalizedRectangle;
if (normalizedRectangle is null)
continue;
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
continue;
if (face.Mapping.MappingFromPhotoPrismCollection is null)
continue;
(_, normalizedRectangleToPersonContainers) = mapLogic.GetNormalizedRectangleToPersonContainers(face.Mapping.MappingFromItem.Id);
if (normalizedRectangleToPersonContainers is null || !normalizedRectangleToPersonContainers.TryGetValue(normalizedRectangle.Value, out personContainers))
continue;
dlibRectangle = new(face.Location.Left, face.Location.Top, face.Location.Right - face.Location.Left, face.Location.Bottom - face.Location.Top);
foreach (MappingFromPhotoPrism mappingFromPhotoPrism in face.Mapping.MappingFromPhotoPrismCollection)
{
foreach (Shared.Models.Marker marker in mappingFromPhotoPrism.Markers)
{
prismRectangle = ILocation.GetRectangle(mappingFromPhotoPrism.DatabaseFile, marker, face.OutputResolution);
if (prismRectangle is null)
continue;
intersectRectangle = System.Drawing.Rectangle.Intersect(dlibRectangle, prismRectangle.Value);
if (intersectRectangle.Width == 0 || intersectRectangle.Height == 0)
continue;
percent = (double)intersectRectangle.Width * intersectRectangle.Height / (dlibRectangle.Width * dlibRectangle.Height);
if (percent < rectangleIntersectMinimum)
continue;
collection.Add(new(mappingFromPhotoPrism, marker, percent));
}
}
if (!collection.Any())
continue;
sortedCollection = collection.OrderByDescending(l => l.Percent).ToArray();
PopulateSubjects(mappingDefaultName, personBirthdayFormat, subjects, stringBuilder, personContainers, sortedCollection);
}
if (subjects.Any())
{
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-subject_alias_update.sql");
text = string.Join(Environment.NewLine, subjects.Distinct());
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
file = Path.Combine(fPhotoPrismContentDirectory, $"{ticks}-{rectangleIntersectMinimum}-marker_name_update.sql");
text = stringBuilder.ToString();
_ = IPath.WriteAllText(file, text, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
}
internal static string HexStringToString(string text)
{
string result;
if (text.Length < 2 || text[0] != '0' || text[1] != 'x')
result = text;
else
{
string after = text[2..];
byte[] bytes = Enumerable.Range(0, after.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(after.Substring(x, 2), 16))
.ToArray();
result = Encoding.UTF8.GetString(bytes);
}
return result;
}
}