Removed Obsolete A_Property Methods
Changed GetDimensions to handle a stream at the end and one exit Switched to using Action? over IDlibDotNet for Tick method
This commit is contained in:
12
.vscode/tasks.json
vendored
12
.vscode/tasks.json
vendored
@ -148,6 +148,18 @@
|
|||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "buildDuplicateSearch",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/Duplicate-Search/Duplicate-Search.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
|
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Text.Json;
|
||||||
using View_by_Distance.Shared.Models;
|
using View_by_Distance.Shared.Models;
|
||||||
using View_by_Distance.Shared.Models.Properties;
|
using View_by_Distance.Shared.Models.Properties;
|
||||||
using View_by_Distance.Shared.Models.Stateless.Methods;
|
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
@ -57,7 +58,7 @@ internal abstract class Container
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string _)
|
internal static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
Models.Container[] results;
|
Models.Container[] results;
|
||||||
@ -101,11 +102,11 @@ internal abstract class Container
|
|||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(string aResultsFullGroupDirectory, _) = dlibDotNet.GetResultsFullGroupDirectories();
|
(_, string bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
string bMetadataSingletonDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultSingleton);
|
||||||
if (!Directory.Exists(aPropertySingletonDirectory))
|
if (!Directory.Exists(bMetadataSingletonDirectory))
|
||||||
_ = Directory.CreateDirectory(aPropertySingletonDirectory);
|
_ = Directory.CreateDirectory(bMetadataSingletonDirectory);
|
||||||
List<FilePair> filePairs = GetFilePairs(dlibDotNet, propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter);
|
List<FilePair> filePairs = GetFilePairs(propertyConfiguration, bMetadataSingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter, dlibDotNet.Tick);
|
||||||
foreach (FilePair filePair in filePairs)
|
foreach (FilePair filePair in filePairs)
|
||||||
{
|
{
|
||||||
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
if (!directoryToItems.TryGetValue(filePair.FilePath.DirectoryFullPath, out items))
|
||||||
@ -126,24 +127,24 @@ internal abstract class Container
|
|||||||
return (filePairs.Count, results.ToArray());
|
return (filePairs.Count, results.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<FilePair> GetFilePairs(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, ReadOnlyDictionary<int, ExifDirectory>? exifDirectoriesById, string directorySearchFilter)
|
private static List<FilePair> GetFilePairs(IPropertyConfiguration propertyConfiguration, string bMetadataSingletonDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, ReadOnlyDictionary<int, ExifDirectory>? exifDirectoriesById, string directorySearchFilter, Action? tick)
|
||||||
{
|
{
|
||||||
List<FilePair> results = [];
|
List<FilePair> results = [];
|
||||||
const string extension = ".json";
|
const string extension = ".json";
|
||||||
ReadOnlyCollection<Shared.Models.FilePair> filePairs;
|
ReadOnlyCollection<Shared.Models.FilePair> filePairs;
|
||||||
string jsonGroupDirectory = aPropertySingletonDirectory;
|
string jsonGroupDirectory = bMetadataSingletonDirectory;
|
||||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
||||||
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
int filesCollectionDirectoryLength = filesCollectionDirectory.Length;
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
filePairs = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
|
filePairs = IFilePair.GetFilePairs(propertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
|
||||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
|
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) =>
|
||||||
ParallelFor(dlibDotNet, propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, exifDirectoriesById, filePairs[i], results));
|
ParallelFor(propertyConfiguration, jsonGroupDirectory, extension, keyValuePairs, splatNineIdentifiers, filesCollectionDirectoryLength, exifDirectoriesById, filePairs[i], results, tick));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParallelFor(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, ReadOnlyDictionary<int, ExifDirectory>? exifDirectoriesById, Shared.Models.FilePair filePair, List<FilePair> results)
|
private static void ParallelFor(IPropertyConfiguration propertyConfiguration, string jsonGroupDirectory, string extension, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, int rootDirectoryLength, ReadOnlyDictionary<int, ExifDirectory>? exifDirectoriesById, Shared.Models.FilePair filePair, List<FilePair> results, Action? tick)
|
||||||
{
|
{
|
||||||
dlibDotNet?.Tick();
|
tick?.Invoke();
|
||||||
bool abandoned = false;
|
bool abandoned = false;
|
||||||
FileHolder sourceDirectoryFileHolder;
|
FileHolder sourceDirectoryFileHolder;
|
||||||
if (exifDirectoriesById is null || filePair.FilePath.Id is null || !exifDirectoriesById.TryGetValue(filePair.FilePath.Id.Value, out ExifDirectory? exifDirectory))
|
if (exifDirectoriesById is null || filePair.FilePath.Id is null || !exifDirectoriesById.TryGetValue(filePair.FilePath.Id.Value, out ExifDirectory? exifDirectory))
|
||||||
@ -208,7 +209,14 @@ internal abstract class Container
|
|||||||
string jsonFileName = $"{fileName}{extension}";
|
string jsonFileName = $"{fileName}{extension}";
|
||||||
string fullFileName = Path.Combine(directory, jsonFileName);
|
string fullFileName = Path.Combine(directory, jsonFileName);
|
||||||
MoveIf(jsonFileName, cei, directory, fullFileName);
|
MoveIf(jsonFileName, cei, directory, fullFileName);
|
||||||
sourceDirectoryFileHolder = IFileHolder.Get(fullFileName);
|
FileInfo fileInfo = new(fullFileName);
|
||||||
|
if (exifDirectory is not null && !fileInfo.Exists)
|
||||||
|
{
|
||||||
|
string json = JsonSerializer.Serialize(exifDirectory, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
||||||
|
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
|
||||||
|
fileInfo.Refresh();
|
||||||
|
}
|
||||||
|
sourceDirectoryFileHolder = IFileHolder.Get(fileInfo);
|
||||||
}
|
}
|
||||||
if (sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && filePair.FilePath.LastWriteTicks != sourceDirectoryFileHolder.CreationTime.Value.Ticks)
|
if (sourceDirectoryFileHolder.CreationTime is not null && sourceDirectoryFileHolder.LastWriteTime is not null && filePair.FilePath.LastWriteTicks != sourceDirectoryFileHolder.CreationTime.Value.Ticks)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,8 @@ namespace View_by_Distance.Container.Models.Stateless.Methods;
|
|||||||
public interface IContainer
|
public interface IContainer
|
||||||
{
|
{
|
||||||
|
|
||||||
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers) =>
|
||||||
Container.GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
Container.GetContainers(propertyConfiguration, splatNineIdentifiers);
|
||||||
|
|
||||||
public static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
public static DateTime[] GetContainerDateTimes(ReadOnlyCollection<Item> items) =>
|
||||||
Container.GetContainerDateTimes(items);
|
Container.GetContainerDateTimes(items);
|
||||||
@ -17,8 +17,8 @@ public interface IContainer
|
|||||||
public static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
public static ReadOnlyCollection<Item> GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
Container.GetValidImageItems(propertyConfiguration, container);
|
Container.GetValidImageItems(propertyConfiguration, container);
|
||||||
|
|
||||||
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
public static (int, Models.Container[]) GetContainers(IPropertyConfiguration propertyConfiguration) =>
|
||||||
GetContainers(propertyConfiguration, null, aPropertySingletonDirectory);
|
GetContainers(propertyConfiguration, splatNineIdentifiers: null);
|
||||||
|
|
||||||
public static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
public static List<int> GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
@ -38,8 +38,8 @@ public interface IContainer
|
|||||||
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, Models.Container container) =>
|
||||||
GetValidImageItems(propertyConfiguration, container);
|
GetValidImageItems(propertyConfiguration, container);
|
||||||
|
|
||||||
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory) =>
|
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration) =>
|
||||||
GetContainers(propertyConfiguration, aPropertySingletonDirectory);
|
GetContainers(propertyConfiguration);
|
||||||
|
|
||||||
internal List<int> TestStatic_GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
internal List<int> TestStatic_GetFilteredDistinctIds(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
|
||||||
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
@ -50,8 +50,8 @@ public interface IContainer
|
|||||||
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
internal ReadOnlyCollection<Item> TestStatic_GetValidImageItems(IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
|
||||||
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
GetValidImageItems(propertyConfiguration, containers, distinctItems, filterItems);
|
||||||
|
|
||||||
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, string aPropertySingletonDirectory) =>
|
internal (int, Models.Container[]) TestStatic_GetContainers(IPropertyConfiguration propertyConfiguration, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers) =>
|
||||||
GetContainers(propertyConfiguration, splatNineIdentifiers, aPropertySingletonDirectory);
|
GetContainers(propertyConfiguration, splatNineIdentifiers);
|
||||||
|
|
||||||
internal ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById) =>
|
internal ReadOnlyCollection<Models.Container> TestStatic_GetContainers(IDlibDotNet dlibDotNet, IPropertyConfiguration propertyConfiguration, string facesFileNameExtension, string facesHiddenFileNameExtension, string eDistanceContentDirectory, string filesCollectionDirectory, ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>>? keyValuePairs, ReadOnlyDictionary<int, Identifier>? splatNineIdentifiers, ReadOnlyCollection<ReadOnlyCollection<FilePath>> filePathsCollection, ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById) =>
|
||||||
GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById);
|
GetContainers(dlibDotNet, propertyConfiguration, facesFileNameExtension, facesHiddenFileNameExtension, eDistanceContentDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Phares.Shared;
|
using Phares.Shared;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -571,14 +571,14 @@ public partial class E_Distance : IDistance
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(IDlibDotNet dlibDotNet, Configuration mapConfiguration, long ticks, MapLogic mapLogic, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding, List<LocationContainer> preFiltered, DistanceLimits distanceLimits, List<LocationContainer> postFiltered)
|
public static ReadOnlyCollection<LocationContainer> GetMatrixLocationContainers(Configuration mapConfiguration, long ticks, MapLogic mapLogic, ReadOnlyDictionary<int, ReadOnlyDictionary<int, LocationContainer>> mappedWithEncoding, List<LocationContainer> preFiltered, DistanceLimits distanceLimits, List<LocationContainer> postFiltered, Action? tick)
|
||||||
{
|
{
|
||||||
List<LocationContainer> results = [];
|
List<LocationContainer> results = [];
|
||||||
ReadOnlyCollection<LocationContainer> locationContainers;
|
ReadOnlyCollection<LocationContainer> locationContainers;
|
||||||
ReadOnlyCollection<LocationContainer> readOnlyLocationContainers = GetReadOnlyLocationContainer(mappedWithEncoding, postFiltered);
|
ReadOnlyCollection<LocationContainer> readOnlyLocationContainers = GetReadOnlyLocationContainer(mappedWithEncoding, postFiltered);
|
||||||
foreach (LocationContainer locationContainer in postFiltered)
|
foreach (LocationContainer locationContainer in postFiltered)
|
||||||
{
|
{
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
locationContainers = FaceRecognition.GetLocationContainers(mapConfiguration.FaceDistancePermyriad, readOnlyLocationContainers, locationContainer);
|
locationContainers = FaceRecognition.GetLocationContainers(mapConfiguration.FaceDistancePermyriad, readOnlyLocationContainers, locationContainer);
|
||||||
foreach (LocationContainer item in locationContainers)
|
foreach (LocationContainer item in locationContainers)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,6 @@ using Phares.Shared;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using View_by_Distance.Drag_Drop.Models;
|
using View_by_Distance.Drag_Drop.Models;
|
||||||
using View_by_Distance.Property.Models;
|
|
||||||
using View_by_Distance.Resize.Models;
|
using View_by_Distance.Resize.Models;
|
||||||
using View_by_Distance.Shared.Models;
|
using View_by_Distance.Shared.Models;
|
||||||
using View_by_Distance.Shared.Models.Stateless.Methods;
|
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
@ -20,7 +19,7 @@ public partial class DragDropSearch : Form
|
|||||||
private readonly IsEnvironment _IsEnvironment;
|
private readonly IsEnvironment _IsEnvironment;
|
||||||
private readonly Dictionary<int, Item> _IdToItem;
|
private readonly Dictionary<int, Item> _IdToItem;
|
||||||
private readonly string _ResizeFileNameExtension;
|
private readonly string _ResizeFileNameExtension;
|
||||||
private readonly Models.Configuration _Configuration;
|
private readonly Configuration _Configuration;
|
||||||
private readonly IConfigurationRoot _ConfigurationRoot;
|
private readonly IConfigurationRoot _ConfigurationRoot;
|
||||||
private readonly Property.Models.Configuration _PropertyConfiguration;
|
private readonly Property.Models.Configuration _PropertyConfiguration;
|
||||||
|
|
||||||
@ -30,8 +29,8 @@ public partial class DragDropSearch : Form
|
|||||||
_IdToItem = [];
|
_IdToItem = [];
|
||||||
AppSettings appSettings;
|
AppSettings appSettings;
|
||||||
string workingDirectory;
|
string workingDirectory;
|
||||||
|
Configuration configuration;
|
||||||
IsEnvironment isEnvironment;
|
IsEnvironment isEnvironment;
|
||||||
Models.Configuration configuration;
|
|
||||||
IConfigurationRoot configurationRoot;
|
IConfigurationRoot configurationRoot;
|
||||||
Property.Models.Configuration propertyConfiguration;
|
Property.Models.Configuration propertyConfiguration;
|
||||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
@ -93,8 +92,7 @@ public partial class DragDropSearch : Form
|
|||||||
private void LoadData()
|
private void LoadData()
|
||||||
{
|
{
|
||||||
Container.Models.Container[] containers;
|
Container.Models.Container[] containers;
|
||||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), "{}");
|
(_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration);
|
||||||
(_, containers) = View_by_Distance.Container.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
|
|
||||||
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
|
List<Item> collection = Program.GetItemCollection(_Configuration, containers);
|
||||||
foreach (Item item in collection)
|
foreach (Item item in collection)
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ using View_by_Distance.Duplicate.Search.Models;
|
|||||||
using View_by_Distance.Property.Models;
|
using View_by_Distance.Property.Models;
|
||||||
using View_by_Distance.Shared.Models;
|
using View_by_Distance.Shared.Models;
|
||||||
using View_by_Distance.Shared.Models.Methods;
|
using View_by_Distance.Shared.Models.Methods;
|
||||||
|
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
namespace View_by_Distance.Duplicate.Search;
|
namespace View_by_Distance.Duplicate.Search;
|
||||||
|
|
||||||
@ -71,8 +72,7 @@ public class DuplicateSearch
|
|||||||
using (ProgressBar progressBar = new(1, message, options))
|
using (ProgressBar progressBar = new(1, message, options))
|
||||||
{
|
{
|
||||||
progressBar.Tick();
|
progressBar.Tick();
|
||||||
string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A_Property), "{}");
|
(f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration);
|
||||||
(f, containers) = Container.Models.Stateless.Methods.IContainer.GetContainers(configuration, aPropertySingletonDirectory);
|
|
||||||
}
|
}
|
||||||
return containers;
|
return containers;
|
||||||
}
|
}
|
||||||
@ -101,12 +101,15 @@ public class DuplicateSearch
|
|||||||
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List<int> preloadIds)
|
private static Dictionary<int, List<MappingFromItem?>> GetIdToCollection(string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory, Container.Models.Container[] containers, string destinationRoot, List<int> preloadIds)
|
||||||
{
|
{
|
||||||
Dictionary<int, List<MappingFromItem?>> results = [];
|
Dictionary<int, List<MappingFromItem?>> results = [];
|
||||||
|
string? model;
|
||||||
string directory;
|
string directory;
|
||||||
const int zero = 0;
|
const int zero = 0;
|
||||||
|
DateTime? dateTime;
|
||||||
FileHolder resizedFileHolder;
|
FileHolder resizedFileHolder;
|
||||||
DateTime[] containerDateTimes;
|
DateTime[] containerDateTimes;
|
||||||
MappingFromItem? mappingFromItem;
|
MappingFromItem? mappingFromItem;
|
||||||
List<MappingFromItem?>? collection;
|
List<MappingFromItem?>? collection;
|
||||||
|
ReadOnlyCollection<string> keywords;
|
||||||
ReadOnlyCollection<Item> validImageItems;
|
ReadOnlyCollection<Item> validImageItems;
|
||||||
const string duplicates = "-Duplicate(s)";
|
const string duplicates = "-Duplicate(s)";
|
||||||
if (containers.Length != 0)
|
if (containers.Length != 0)
|
||||||
@ -145,12 +148,15 @@ public class DuplicateSearch
|
|||||||
mappingFromItem = collection[zero];
|
mappingFromItem = collection[zero];
|
||||||
if (mappingFromItem is not null)
|
if (mappingFromItem is not null)
|
||||||
{
|
{
|
||||||
|
dateTime = IDate.GetDateTimeOriginal(item.ExifDirectory);
|
||||||
|
keywords = IMetaBase.GetKeywords(item.ExifDirectory?.ExifBaseDirectories);
|
||||||
|
model = Metadata.Models.Stateless.Methods.IMetadata.GetModel(item.ExifDirectory);
|
||||||
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
|
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(mappingFromItem.ResizedFileHolder.FullName.Replace($"0{duplicates}", $"1{duplicates}"));
|
||||||
collection[0] = new(mappingFromItem.ContainerDateTimes, item.Property.DateTimeDigitized, item.Property.DateTimeOriginal, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, item.Property.Keywords ?? [], mappingFromItem.MinimumDateTime, item.Property.Model, mappingFromItem.RelativePath, resizedFileHolder);
|
collection[0] = new(mappingFromItem.ContainerDateTimes, dateTime, mappingFromItem.Id, mappingFromItem.IsArchive, mappingFromItem.FilePath, mappingFromItem.IsWrongYear, keywords, mappingFromItem.MinimumDateTime, model, mappingFromItem.RelativePath, resizedFileHolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
|
resizedFileHolder = Shared.Models.Stateless.Methods.IFileHolder.Get(string.Concat(Path.Combine(destinationRoot, directory), item.RelativePath));
|
||||||
mappingFromItem = Shared.Models.Stateless.Methods.IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
|
mappingFromItem = IMappingFromItem.GetMappingFromItem(containerDateTimes, item, resizedFileHolder);
|
||||||
collection.Add(mappingFromItem);
|
collection.Add(mappingFromItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
_Exceptions = [];
|
_Exceptions = [];
|
||||||
_Console = console;
|
_Console = console;
|
||||||
_AppSettings = appSettings;
|
_AppSettings = appSettings;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
_IsEnvironment = isEnvironment;
|
_IsEnvironment = isEnvironment;
|
||||||
long ticks = DateTime.Now.Ticks;
|
long ticks = DateTime.Now.Ticks;
|
||||||
_JLinkResolvedDirectories = [];
|
_JLinkResolvedDirectories = [];
|
||||||
@ -128,8 +129,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
message = $") Building People Collection - {totalSeconds} total second(s)";
|
message = $") Building People Collection - {totalSeconds} total second(s)";
|
||||||
using ProgressBar progressBar = new(1, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(1, message);
|
||||||
progressBar.Tick();
|
dlibDotNet.Tick();
|
||||||
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
|
string peopleRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(A2_People));
|
||||||
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception();
|
string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception();
|
||||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, propertyConfiguration.ResultSingleton));
|
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, propertyConfiguration.ResultSingleton));
|
||||||
@ -196,7 +197,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string[] changesFrom = [nameof(A_Property)];
|
string[] changesFrom = [nameof(A_Property)];
|
||||||
List<Tuple<string, DateTime>> subFileTuples = [];
|
List<Tuple<string, DateTime>> subFileTuples = [];
|
||||||
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
|
FileHolder resizedFileHolder = _Resize.GetResizedFileHolder(cResultsFullGroupDirectory, item, outputResolutionHasNumber);
|
||||||
if (item.ExifDirectory is null || item.ExifDirectory.FilePath.Id is null || !item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
|
if (item.ExifDirectory is null || item.ExifDirectory.FilePath.Id is null)
|
||||||
|
throw new Exception();
|
||||||
|
if (!item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
|
if (_Configuration.PropertyConfiguration.ForcePropertyLastWriteTimeToCreationTime && item.SourceDirectoryFileHolder.LastWriteTime.Value != item.SourceDirectoryFileHolder.CreationTime.Value)
|
||||||
{
|
{
|
||||||
@ -327,12 +330,13 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int exceptionsCount = 0;
|
int exceptionsCount = 0;
|
||||||
|
IDlibDotNet dlibDotNet = this;
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
||||||
DateTime[] containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
DateTime[] containerDateTimes = Container.Models.Stateless.Methods.IContainer.GetContainerDateTimes(filteredItems);
|
||||||
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
string focusRelativePath = Path.GetFullPath(string.Concat(_Configuration.PropertyConfiguration.RootDirectory, _Configuration.FocusDirectory));
|
||||||
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
bool? isFocusRelativePath = string.IsNullOrEmpty(_Configuration.FocusDirectory) ? null : container.SourceDirectory.StartsWith(focusRelativePath);
|
||||||
bool anyPropertiesChangedForX = _Configuration.PropertyConfiguration.PropertiesChangedForProperty || _Configuration.PropertiesChangedForDistance || _Configuration.PropertiesChangedForFaces || _Configuration.PropertiesChangedForIndex || _Configuration.PropertiesChangedForMetadata || _Configuration.PropertiesChangedForResize;
|
bool anyPropertiesChangedForX = _Configuration.PropertyConfiguration.PropertiesChangedForProperty || _Configuration.PropertiesChangedForDistance || _Configuration.PropertiesChangedForFaces || _Configuration.PropertiesChangedForIndex || _Configuration.PropertiesChangedForMetadata || _Configuration.PropertiesChangedForResize;
|
||||||
using ProgressBar progressBar = new(filteredItems.Count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(filteredItems.Count, message);
|
||||||
_ = Parallel.For(0, filteredItems.Count, parallelOptions, (i, state) =>
|
_ = Parallel.For(0, filteredItems.Count, parallelOptions, (i, state) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -351,7 +355,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
containerDateTimes,
|
containerDateTimes,
|
||||||
isFocusRelativePath);
|
isFocusRelativePath);
|
||||||
if (!anyPropertiesChangedForX && (i == 0 || sourceDirectoryChanges.Count > 0))
|
if (!anyPropertiesChangedForX && (i == 0 || sourceDirectoryChanges.Count > 0))
|
||||||
progressBar.Tick();
|
dlibDotNet.Tick();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@ -450,8 +454,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
}
|
}
|
||||||
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
||||||
message = $"{totalSeconds} total second(s) - {outputResolution} - ### [###] / {readOnlyContainers.Count:000} - {total} / {count} total - <> - total not mapped {totalNotMapped:000000}";
|
message = $"{totalSeconds} total second(s) - {outputResolution} - ### [###] / {readOnlyContainers.Count:000} - {total} / {count} total - <> - total not mapped {totalNotMapped:000000}";
|
||||||
using ProgressBar progressBar = new(1, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(1, message);
|
||||||
progressBar.Tick();
|
dlibDotNet.Tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,7 +611,11 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
ExifDirectory? result;
|
ExifDirectory? result;
|
||||||
if (filePair.Match is null)
|
if (filePair.Match is null)
|
||||||
result = null;
|
{
|
||||||
|
try
|
||||||
|
{ result = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePair.FilePath); }
|
||||||
|
catch (Exception) { result = null; }
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string json = File.ReadAllText(filePair.Match.FullName);
|
string json = File.ReadAllText(filePair.Match.FullName);
|
||||||
@ -1003,9 +1011,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
return results.AsReadOnly();
|
return results.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParallelFor(IDlibDotNet dlibDotNet, FilePair filePair, Dictionary<int, ExifDirectory> results)
|
private void ParallelFor(FilePair filePair, Dictionary<int, ExifDirectory> results, Action? tick)
|
||||||
{
|
{
|
||||||
dlibDotNet?.Tick();
|
tick?.Invoke();
|
||||||
if (filePair.FilePath.Id is null || results.ContainsKey(filePair.FilePath.Id.Value))
|
if (filePair.FilePath.Id is null || results.ContainsKey(filePair.FilePath.Id.Value))
|
||||||
return;
|
return;
|
||||||
ExifDirectory? exifDirectory = GetExifDirectory(filePair);
|
ExifDirectory? exifDirectory = GetExifDirectory(filePair);
|
||||||
@ -1087,7 +1095,6 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
const string directorySearchFilter = "*";
|
const string directorySearchFilter = "*";
|
||||||
bool configurationOutputResolutionsHas = false;
|
bool configurationOutputResolutionsHas = false;
|
||||||
ReadOnlyDictionary<long, List<int>> personKeyToIds;
|
ReadOnlyDictionary<long, List<int>> personKeyToIds;
|
||||||
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
|
|
||||||
string[] checkDirectories =
|
string[] checkDirectories =
|
||||||
[
|
[
|
||||||
Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "Ancestry"),
|
Path.Combine(_Configuration.PropertyConfiguration.RootDirectory, "Ancestry"),
|
||||||
@ -1096,6 +1103,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
];
|
];
|
||||||
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks, checkDirectories);
|
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(_Configuration, ticks, checkDirectories);
|
||||||
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories();
|
||||||
|
(int season, string seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear);
|
||||||
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
|
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
|
||||||
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
|
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
|
||||||
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
|
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent);
|
||||||
@ -1145,30 +1153,25 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
if (outputResolution.Any(char.IsNumber))
|
if (outputResolution.Any(char.IsNumber))
|
||||||
continue;
|
continue;
|
||||||
Dictionary<int, ExifDirectory> exifDirectoriesById = [];
|
bool filesCollectionCountIsOne = record?.FilesCollectionCountIsOne ?? false;
|
||||||
(cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, _, _, _) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
string? filesCollectionRootDirectory = Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
ReadOnlyDictionary<int, ExifDirectory> exifDirectoriesById = record?.ExifDirectoriesById ?? new(new Dictionary<int, ExifDirectory>());
|
||||||
|
string? filesCollectionRootDirectory = record?.FilesCollectionRootDirectory ?? Path.Combine(cResultsFullGroupDirectory, _Configuration.PropertyConfiguration.ResultContent);
|
||||||
ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useIgnoreExtensions: true, useCeilingAverage: true);
|
ReadOnlyCollection<ReadOnlyCollection<FilePath>>? filePathsCollection = IDirectory.GetFilePathCollections(_Configuration.PropertyConfiguration, directorySearchFilter, fileSearchFilter, filesCollectionRootDirectory, useIgnoreExtensions: true, useCeilingAverage: true);
|
||||||
record = new(FilesCollectionRootDirectory: filesCollectionRootDirectory,
|
record = new(FilesCollectionRootDirectory: filesCollectionRootDirectory,
|
||||||
FilesCollectionCountIsOne: false,
|
FilesCollectionCountIsOne: filesCollectionCountIsOne,
|
||||||
FilePathsCollection: filePathsCollection,
|
FilePathsCollection: filePathsCollection,
|
||||||
ExifDirectoriesById: new(exifDirectoriesById),
|
ExifDirectoriesById: exifDirectoriesById,
|
||||||
IdToFilePaths: null,
|
IdToFilePaths: record?.IdToFilePaths,
|
||||||
SplatNineIdentifiers: null);
|
SplatNineIdentifiers: record?.SplatNineIdentifiers);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (string.IsNullOrEmpty(record?.FilesCollectionRootDirectory) || record.FilePathsCollection.Count == 0)
|
if (string.IsNullOrEmpty(record?.FilesCollectionRootDirectory) || record.FilePathsCollection.Count == 0)
|
||||||
throw new NullReferenceException(nameof(record.FilePathsCollection));
|
throw new NullReferenceException(nameof(record.FilePathsCollection));
|
||||||
foreach (string checkDirectory in checkDirectories)
|
|
||||||
{
|
|
||||||
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}");
|
|
||||||
if (!Directory.Exists(seasonDirectory))
|
|
||||||
_ = Directory.CreateDirectory(seasonDirectory);
|
|
||||||
}
|
|
||||||
int count = record.FilePathsCollection.Select(l => l.Count).Sum();
|
int count = record.FilePathsCollection.Select(l => l.Count).Sum();
|
||||||
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
message = $") Building Container(s) - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
_ProgressBar = new(count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(count, message);
|
||||||
ReadOnlyCollection<Container.Models.Container> readOnlyContainers =
|
ReadOnlyCollection<Container.Models.Container> readOnlyContainers =
|
||||||
Container.Models.Stateless.Methods.IContainer.GetContainers(dlibDotNet,
|
Container.Models.Stateless.Methods.IContainer.GetContainers(dlibDotNet,
|
||||||
_Configuration.PropertyConfiguration,
|
_Configuration.PropertyConfiguration,
|
||||||
@ -1180,20 +1183,18 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
record.SplatNineIdentifiers,
|
record.SplatNineIdentifiers,
|
||||||
record.FilePathsCollection,
|
record.FilePathsCollection,
|
||||||
record.ExifDirectoriesById);
|
record.ExifDirectoriesById);
|
||||||
_ProgressBar.Dispose();
|
Verify(argZero, readOnlyContainers);
|
||||||
|
foreach (string checkDirectory in checkDirectories)
|
||||||
|
{
|
||||||
|
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}");
|
||||||
|
if (!Directory.Exists(seasonDirectory))
|
||||||
|
_ = Directory.CreateDirectory(seasonDirectory);
|
||||||
|
}
|
||||||
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
|
||||||
DeleteContinueFiles(personContainers);
|
DeleteContinueFiles(personContainers);
|
||||||
if (!runToDoCollectionFirst)
|
if (!runToDoCollectionFirst)
|
||||||
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory);
|
MapFaceFileLogic(ticks, personContainers, mapLogic, a2PeopleContentDirectory, eDistanceContentDirectory);
|
||||||
FullDoWork(argZero,
|
FullDoWork(argZero, propertyRoot, ticks, fPhotoPrismSingletonDirectory, count, metadata, record, readOnlyContainers, mapLogic);
|
||||||
propertyRoot,
|
|
||||||
ticks,
|
|
||||||
fPhotoPrismSingletonDirectory,
|
|
||||||
count,
|
|
||||||
metadata,
|
|
||||||
record,
|
|
||||||
readOnlyContainers,
|
|
||||||
mapLogic);
|
|
||||||
ReadOnlyCollection<Item> distinctValidImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
|
ReadOnlyCollection<Item> distinctValidImageItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
|
||||||
if (_Configuration.LookForAbandoned)
|
if (_Configuration.LookForAbandoned)
|
||||||
{
|
{
|
||||||
@ -1201,10 +1202,9 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
string d2ResultsFullGroupDirectory;
|
string d2ResultsFullGroupDirectory;
|
||||||
foreach (string outputResolution in _Configuration.OutputResolutions)
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
{
|
{
|
||||||
_ProgressBar = new(5, nameof(mapLogic.LookForAbandoned), _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(5, nameof(mapLogic.LookForAbandoned));
|
||||||
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = dlibDotNet.GetResultsFullGroupDirectories(outputResolution);
|
||||||
mapLogic.LookForAbandoned(dlibDotNet, _Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
|
mapLogic.LookForAbandoned(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, dlibDotNet.Tick);
|
||||||
_ProgressBar.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_Distance.Clear();
|
_Distance.Clear();
|
||||||
@ -1253,12 +1253,49 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Verify(string argZero, ReadOnlyCollection<Container.Models.Container> readOnlyContainers)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
List<Item> items = [];
|
||||||
|
Container.Models.Container container;
|
||||||
|
ReadOnlyCollection<Item> filteredItems;
|
||||||
|
foreach (string outputResolution in _Configuration.OutputResolutions)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < readOnlyContainers.Count; i++)
|
||||||
|
{
|
||||||
|
container = readOnlyContainers[i];
|
||||||
|
if (container.Items.Count == 0)
|
||||||
|
continue;
|
||||||
|
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
|
||||||
|
continue;
|
||||||
|
filteredItems = Container.Models.Stateless.Methods.IContainer.GetValidImageItems(_Configuration.PropertyConfiguration, container);
|
||||||
|
if (filteredItems.Count == 0)
|
||||||
|
continue;
|
||||||
|
foreach (Item item in filteredItems)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
if (item.ExifDirectory is null || item.ExifDirectory.FilePath.Id is null)
|
||||||
|
{
|
||||||
|
items.Add(item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!item.SourceDirectoryFileHolder.Exists || item.SourceDirectoryFileHolder.CreationTime is null || item.SourceDirectoryFileHolder.LastWriteTime is null || item.Any())
|
||||||
|
{
|
||||||
|
items.Add(item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (items.Count > 0)
|
||||||
|
throw new Exception($"{items.Count} item(s) of {count} item(s) are not setup!");
|
||||||
|
}
|
||||||
|
|
||||||
private Record GetFilesCollectionThenCopyOrMove(IDlibDotNet dlibDotNet, long ticks, string fileSearchFilter, string directorySearchFilter, string bResultsFullGroupDirectory, string outputResolution)
|
private Record GetFilesCollectionThenCopyOrMove(IDlibDotNet dlibDotNet, long ticks, string fileSearchFilter, string directorySearchFilter, string bResultsFullGroupDirectory, string outputResolution)
|
||||||
{
|
{
|
||||||
Record result;
|
Record result;
|
||||||
int count;
|
int count;
|
||||||
string message;
|
string message;
|
||||||
ProgressBar progressBar;
|
|
||||||
const string extension = ".json";
|
const string extension = ".json";
|
||||||
ReadOnlyCollection<FilePair> filePairs;
|
ReadOnlyCollection<FilePair> filePairs;
|
||||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
||||||
@ -1276,24 +1313,23 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
count = filePathsCollection.Select(l => l.Count).Sum();
|
count = filePathsCollection.Select(l => l.Count).Sum();
|
||||||
filePairs = IFilePair.GetFilePairs(_Configuration.PropertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
|
filePairs = IFilePair.GetFilePairs(_Configuration.PropertyConfiguration, directorySearchFilter, extension, jsonGroupDirectory, filePathsCollection);
|
||||||
message = $") Preloading ExifDirectory Dictionary - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
message = $") Preloading ExifDirectory Dictionary - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
progressBar = new(count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(count, message);
|
||||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, filePairs[i], exifDirectoriesById));
|
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(filePairs[i], exifDirectoriesById, dlibDotNet.Tick));
|
||||||
progressBar.Dispose();
|
if (exifDirectoriesById.Count == 0)
|
||||||
|
throw new Exception("No exif directories were found!");
|
||||||
count = filePathsCollection.Select(l => l.Count).Sum();
|
count = filePathsCollection.Select(l => l.Count).Sum();
|
||||||
bool filesCollectionCountIsOne = GetFilesCollectionCountIsOne(filePathsCollection);
|
bool filesCollectionCountIsOne = GetFilesCollectionCountIsOne(filePathsCollection);
|
||||||
message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
message = $") Selecting for ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
progressBar = new(count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(count, message);
|
||||||
(string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups, exifDirectoriesById, () => progressBar.Tick());
|
(string[] distinctDirectories, List<(FilePath, string)> toDoCollection) = IDirectory.GetToDoCollection(_Configuration.PropertyConfiguration, filePathsCollection, fileGroups, exifDirectoriesById, dlibDotNet.Tick);
|
||||||
progressBar.Dispose();
|
|
||||||
foreach (string distinctDirectory in distinctDirectories)
|
foreach (string distinctDirectory in distinctDirectories)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(distinctDirectory))
|
if (!Directory.Exists(distinctDirectory))
|
||||||
_ = Directory.CreateDirectory(distinctDirectory);
|
_ = Directory.CreateDirectory(distinctDirectory);
|
||||||
}
|
}
|
||||||
message = $") Copying to ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
message = $") Copying to ## pattern directory - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
progressBar = new(count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(count, message);
|
||||||
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, () => progressBar.Tick());
|
_ = IDirectory.CopyOrMove(toDoCollection, move: false, moveBack: false, dlibDotNet.Tick);
|
||||||
progressBar.Dispose();
|
|
||||||
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> idToFilePaths = FilePath.GetKeyValuePairs(filePathsCollection);
|
ReadOnlyDictionary<int, ReadOnlyCollection<FilePath>> idToFilePaths = FilePath.GetKeyValuePairs(filePathsCollection);
|
||||||
ReadOnlyDictionary<int, Identifier> splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, idToFilePaths);
|
ReadOnlyDictionary<int, Identifier> splatNineIdentifiers = GetSplatNineIdentifiersAndHideSplatNine(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, idToFilePaths);
|
||||||
result = new(ExifDirectoriesById: new(exifDirectoriesById),
|
result = new(ExifDirectoriesById: new(exifDirectoriesById),
|
||||||
@ -1362,9 +1398,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
string message = $") Building Matrix - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)";
|
||||||
_ProgressBar = new(postFiltered.Count, message, _ProgressBarOptions);
|
dlibDotNet.ConstructProgressBar(postFiltered.Count, message);
|
||||||
ReadOnlyCollection<LocationContainer> matrix = E_Distance.GetMatrixLocationContainers(dlibDotNet, _MapConfiguration, ticks, mapLogic, mappedWithEncoding, preFiltered, distanceLimits, postFiltered);
|
ReadOnlyCollection<LocationContainer> matrix = E_Distance.GetMatrixLocationContainers(_MapConfiguration, ticks, mapLogic, mappedWithEncoding, preFiltered, distanceLimits, postFiltered, dlibDotNet.Tick);
|
||||||
_ProgressBar.Dispose();
|
|
||||||
ReadOnlyDictionary<string, LocationContainer> onlyOne = GetOnlyOne(distanceLimits, matrix);
|
ReadOnlyDictionary<string, LocationContainer> onlyOne = GetOnlyOne(distanceLimits, matrix);
|
||||||
if (onlyOne.Count == 0)
|
if (onlyOne.Count == 0)
|
||||||
results = [];
|
results = [];
|
||||||
|
@ -921,16 +921,16 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LookForAbandoned(IDlibDotNet dlibDotNet, Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container.Models.Container> readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory)
|
public void LookForAbandoned(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container.Models.Container> readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, Action? tick)
|
||||||
{
|
{
|
||||||
string[] directories;
|
string[] directories;
|
||||||
string? directoryName;
|
string? directoryName;
|
||||||
List<int> distinctFilteredIds = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
List<int> distinctFilteredIds = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
|
||||||
LookForAbandoned(propertyConfiguration, distinctFilteredIds);
|
LookForAbandoned(propertyConfiguration, distinctFilteredIds);
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
List<string> distinctFilteredFileNameFirstSegments = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
List<string> distinctFilteredFileNameFirstSegments = Container.Models.Stateless.Methods.IContainer.GetFilteredDistinctFileNameFirstSegments(propertyConfiguration, readOnlyContainers);
|
||||||
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredFileNameFirstSegments);
|
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredFileNameFirstSegments);
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string directory in directories)
|
foreach (string directory in directories)
|
||||||
{
|
{
|
||||||
@ -939,7 +939,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
continue;
|
continue;
|
||||||
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
||||||
}
|
}
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
directories = Directory.GetDirectories(dResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string directory in directories)
|
foreach (string directory in directories)
|
||||||
{
|
{
|
||||||
@ -948,7 +948,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
continue;
|
continue;
|
||||||
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
||||||
}
|
}
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
directories = Directory.GetDirectories(d2ResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
foreach (string directory in directories)
|
foreach (string directory in directories)
|
||||||
{
|
{
|
||||||
@ -957,7 +957,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
|
|||||||
continue;
|
continue;
|
||||||
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, distinctFilteredFileNameFirstSegments, directory, directoryName);
|
||||||
}
|
}
|
||||||
dlibDotNet.Tick();
|
tick?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LookForAbandoned(Property.Models.Configuration propertyConfiguration, List<int> distinctFilteredIds)
|
private void LookForAbandoned(Property.Models.Configuration propertyConfiguration, List<int> distinctFilteredIds)
|
||||||
|
@ -8,18 +8,18 @@ internal static class Dimensions
|
|||||||
#pragma warning disable IDE0230
|
#pragma warning disable IDE0230
|
||||||
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||||
{
|
{
|
||||||
|
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||||
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||||
|
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
||||||
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
{ 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
|
#pragma warning restore IDE0230
|
||||||
|
|
||||||
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < thatBytes.Length; i += 1)
|
for (int i = 0; i < thisBytes.Count && i < thatBytes.Length; i += 1)
|
||||||
{
|
{
|
||||||
if (thisBytes[i] == thatBytes[i])
|
if (thisBytes[i] == thatBytes[i])
|
||||||
continue;
|
continue;
|
||||||
@ -103,24 +103,41 @@ internal static class Dimensions
|
|||||||
|
|
||||||
internal static Size? GetDimensions(BinaryReader binaryReader)
|
internal static Size? GetDimensions(BinaryReader binaryReader)
|
||||||
{
|
{
|
||||||
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
|
Size? result;
|
||||||
byte[] magicBytes = new byte[maxMagicBytesLength];
|
List<byte> magicBytes = [];
|
||||||
for (int i = 0; i < maxMagicBytesLength; i += 1)
|
int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
|
||||||
|
if (magicBytesLengths.Length == 0)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
magicBytes[i] = binaryReader.ReadByte();
|
result = null;
|
||||||
|
if (binaryReader.BaseStream.Length == binaryReader.BaseStream.Position)
|
||||||
|
_ = binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
for (int i = 0; i < magicBytesLengths[0]; i++)
|
||||||
|
{
|
||||||
|
magicBytes.Add(binaryReader.ReadByte());
|
||||||
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
||||||
{
|
{
|
||||||
if (StartsWith(magicBytes, kvPair.Key))
|
if (StartsWith(magicBytes, kvPair.Key))
|
||||||
return kvPair.Value(binaryReader);
|
{
|
||||||
|
result = kvPair.Value(binaryReader);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
if (result is not null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Size? GetDimensions(string path)
|
internal static Size? GetDimensions(string path)
|
||||||
{
|
{
|
||||||
using BinaryReader binaryReader = new(File.OpenRead(path));
|
Size? result;
|
||||||
return GetDimensions(binaryReader);
|
using FileStream fileStream = File.OpenRead(path);
|
||||||
|
using BinaryReader binaryReader = new(fileStream);
|
||||||
|
result = GetDimensions(binaryReader);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,3 @@
|
|||||||
using ShellProgressBar;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@ -66,40 +65,6 @@ public class A_Property
|
|||||||
converted: false));
|
converted: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use ExifDirectory")]
|
|
||||||
public void SavePropertyParallelWork(long ticks, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, int t, Container.Models.Container[] containers)
|
|
||||||
{
|
|
||||||
int total = 0;
|
|
||||||
string message;
|
|
||||||
int totalSeconds;
|
|
||||||
bool anyNullOrNoIsUniqueFileName;
|
|
||||||
List<Exception> exceptions = [];
|
|
||||||
Container.Models.Container container;
|
|
||||||
int containersLength = containers.Length;
|
|
||||||
const string outputResolution = "Original";
|
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
|
|
||||||
string propertyRoot = IResult.GetResultsGroupDirectory(_PropertyConfiguration, nameof(A_Property));
|
|
||||||
for (int i = 0; i < containers.Length; i++)
|
|
||||||
{
|
|
||||||
container = containers[i];
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
sourceDirectoryChanges.Clear();
|
|
||||||
if (container.Items.Count == 0)
|
|
||||||
continue;
|
|
||||||
anyNullOrNoIsUniqueFileName = container.Items.Any(l => !l.IsUniqueFileName);
|
|
||||||
SetAngleBracketCollection(container.SourceDirectory, anyNullOrNoIsUniqueFileName);
|
|
||||||
totalSeconds = (int)Math.Truncate(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
|
|
||||||
message = $"{i + 1:000} [{container.Items.Count:000}] / {containersLength:000} - {total} / {t} total - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}";
|
|
||||||
SavePropertyParallelWork(_MaxDegreeOfParallelism, metadata, exceptions, sourceDirectoryChanges, container, container.Items, message);
|
|
||||||
if (exceptions.Count == container.Items.Count)
|
|
||||||
throw new Exception(string.Concat("All in [", container.SourceDirectory, "]failed!"));
|
|
||||||
if (exceptions.Count != 0)
|
|
||||||
_ExceptionsDirectories.Add(container.SourceDirectory);
|
|
||||||
total += container.Items.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetAngleBracketCollection(string sourceDirectory, bool anyNullOrNoIsUniqueFileName)
|
private void SetAngleBracketCollection(string sourceDirectory, bool anyNullOrNoIsUniqueFileName)
|
||||||
{
|
{
|
||||||
_AngleBracketCollection.Clear();
|
_AngleBracketCollection.Clear();
|
||||||
@ -112,180 +77,6 @@ public class A_Property
|
|||||||
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use ExifDirectory")]
|
|
||||||
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container.Models.Container container, ReadOnlyCollection<Item> items, string message)
|
|
||||||
{
|
|
||||||
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = [];
|
|
||||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism };
|
|
||||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
||||||
using ProgressBar progressBar = new(items.Count, message, options);
|
|
||||||
_ = Parallel.For(0, items.Count, parallelOptions, (i, state) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
long ticks = DateTime.Now.Ticks;
|
|
||||||
DateTime dateTime = DateTime.Now;
|
|
||||||
List<Tuple<string, DateTime>> collection;
|
|
||||||
SavePropertyParallelForWork(metadata, container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
|
|
||||||
if (i == 0 || sourceDirectoryChanges.Count != 0)
|
|
||||||
progressBar.Tick();
|
|
||||||
lock (sourceDirectoryFileTuples)
|
|
||||||
collection = (from l in sourceDirectoryFileTuples where l.Item2 > dateTime select l).ToList();
|
|
||||||
lock (sourceDirectoryChanges)
|
|
||||||
sourceDirectoryChanges.AddRange(collection);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
lock (exceptions)
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Use ExifDirectory")]
|
|
||||||
private void SavePropertyParallelForWork(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
|
|
||||||
{
|
|
||||||
Shared.Models.Property property;
|
|
||||||
List<string> parseExceptions = [];
|
|
||||||
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered);
|
|
||||||
string filteredSourceDirectoryFileExtensionLowered = Path.Combine(sourceDirectory, $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}");
|
|
||||||
if (item.IsValidImageFormatExtension && item.FilePath.FullName.Length == filteredSourceDirectoryFileExtensionLowered.Length && item.FilePath.FullName != filteredSourceDirectoryFileExtensionLowered)
|
|
||||||
File.Move(item.FilePath.FullName, filteredSourceDirectoryFileExtensionLowered);
|
|
||||||
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.ExifDirectory is null)
|
|
||||||
{
|
|
||||||
property = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
|
|
||||||
lock (sourceDirectoryChanges)
|
|
||||||
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
|
||||||
lock (item)
|
|
||||||
item.Update(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Use ExifDirectory")]
|
|
||||||
private Shared.Models.Property GetImageProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension)
|
|
||||||
{
|
|
||||||
Shared.Models.Property? result;
|
|
||||||
int? id = null;
|
|
||||||
FileInfo fileInfo;
|
|
||||||
string? json = null;
|
|
||||||
bool hasWrongYearProperty = false;
|
|
||||||
string[] changesFrom = [];
|
|
||||||
string angleBracket = _AngleBracketCollection[0];
|
|
||||||
bool populateId = _Configuration.PopulatePropertyId;
|
|
||||||
if (!item.IsUniqueFileName)
|
|
||||||
fileInfo = new(Path.Combine(angleBracket.Replace("<>", _PropertyConfiguration.ResultSingleton), $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json"));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string fileName = $"{item.FilePath.NameWithoutExtension}{item.FilePath.ExtensionLowered}.json";
|
|
||||||
CombinedEnumAndIndex cei = Shared.Models.Stateless.Methods.IPath.GetCombinedEnumAndIndex(_PropertyConfiguration, item.FilePath);
|
|
||||||
string directory = _ResultSingletonFileGroups[0][cei.Enum][cei.Index];
|
|
||||||
fileInfo = new(Path.Combine(directory, fileName));
|
|
||||||
MoveIf(fileName, cei, directory, fileInfo);
|
|
||||||
}
|
|
||||||
List<DateTime> dateTimes = (from l in sourceDirectoryFileTuples where l is not null && changesFrom.Contains(l.Item1) select l.Item2).ToList();
|
|
||||||
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
|
|
||||||
{
|
|
||||||
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
}
|
|
||||||
if (_Configuration.ForcePropertyLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime)
|
|
||||||
{
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
}
|
|
||||||
if (_Configuration.PropertiesChangedForProperty)
|
|
||||||
result = null;
|
|
||||||
else if (!fileInfo.Exists)
|
|
||||||
result = null;
|
|
||||||
else if (!fileInfo.FullName.EndsWith(".json") && !fileInfo.FullName.EndsWith(".old"))
|
|
||||||
throw new ArgumentException("must be a *.json file");
|
|
||||||
else if (dateTimes.Count != 0 && dateTimes.Max() > fileInfo.LastWriteTime)
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
json = File.ReadAllText(fileInfo.FullName);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (item.ExifDirectory is not null)
|
|
||||||
result = null;
|
|
||||||
else
|
|
||||||
result = JsonSerializer.Deserialize(json, PropertyGenerationContext.Default.Property);
|
|
||||||
if (result is not null && json.Contains("WrongYear"))
|
|
||||||
{
|
|
||||||
id = result.Id;
|
|
||||||
hasWrongYearProperty = true;
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
if (!isIgnoreExtension && item.IsValidImageFormatExtension && ((populateId && result?.Id is null) || result?.Width is null || result.Height is null))
|
|
||||||
{
|
|
||||||
id = result?.Id;
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
if (!isIgnoreExtension && item.IsValidImageFormatExtension && populateId && result is not null && result.LastWriteTime.Ticks != item.FilePath.LastWriteTicks)
|
|
||||||
{
|
|
||||||
id = null;
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
if (!isIgnoreExtension && item.IsValidImageFormatExtension && result?.Width is not null && result.Height is not null && result.Width.Value == result.Height.Value)
|
|
||||||
{
|
|
||||||
id = result.Id;
|
|
||||||
result = null;
|
|
||||||
if (result?.Width is not null && result.Height is not null && result.Width.Value != result.Height.Value)
|
|
||||||
throw new Exception("Was square!");
|
|
||||||
}
|
|
||||||
if (!isIgnoreExtension && item.IsValidImageFormatExtension && result is not null && result.FileSize != item.FilePath.Length)
|
|
||||||
{
|
|
||||||
id = result.Id;
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
if (result is not null)
|
|
||||||
{
|
|
||||||
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.LastWriteTime));
|
|
||||||
if (fileInfo.CreationTime != result.LastWriteTime)
|
|
||||||
{
|
|
||||||
File.SetCreationTime(fileInfo.FullName, result.LastWriteTime);
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
parseExceptions.Add(nameof(A_Property));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result is null)
|
|
||||||
{
|
|
||||||
id ??= item.FilePath.Id;
|
|
||||||
(_, _, result) = Stateless.Property.GetProperty(populateId, metadata, item.FilePath, result, isIgnoreExtension, item.IsValidImageFormatExtension, id, _ASCIIEncoding);
|
|
||||||
json = JsonSerializer.Serialize(result, PropertyGenerationContext.Default.Property);
|
|
||||||
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
|
||||||
{
|
|
||||||
File.SetCreationTime(fileInfo.FullName, result.LastWriteTime);
|
|
||||||
if (!_Configuration.ForcePropertyLastWriteTimeToCreationTime)
|
|
||||||
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (hasWrongYearProperty)
|
|
||||||
{
|
|
||||||
json = JsonSerializer.Serialize(result, PropertyGenerationContext.Default.Property);
|
|
||||||
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
|
||||||
{
|
|
||||||
File.SetCreationTime(fileInfo.FullName, result.LastWriteTime);
|
|
||||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime);
|
|
||||||
fileInfo.Refresh();
|
|
||||||
sourceDirectoryFileTuples.Add(new Tuple<string, DateTime>(nameof(A_Property), fileInfo.CreationTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
private static void MoveIf(string fileName, CombinedEnumAndIndex cei, string directory, FileInfo fileInfo)
|
||||||
{
|
{
|
||||||
string[] segments = directory.Split(cei.Combined);
|
string[] segments = directory.Split(cei.Combined);
|
||||||
@ -305,22 +96,4 @@ public class A_Property
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use ExifDirectory")]
|
|
||||||
public Shared.Models.Property GetProperty(Shared.Models.Methods.IMetadata<MetadataExtractor.Directory> metadata, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
|
|
||||||
{
|
|
||||||
Shared.Models.Property result;
|
|
||||||
bool angleBracketCollectionAny = _AngleBracketCollection.Count != 0;
|
|
||||||
if (!angleBracketCollectionAny)
|
|
||||||
{
|
|
||||||
if (item.FilePath.DirectoryFullPath is null)
|
|
||||||
throw new NullReferenceException(nameof(item.FilePath.DirectoryFullPath));
|
|
||||||
SetAngleBracketCollection(item.FilePath.DirectoryFullPath, !item.IsUniqueFileName);
|
|
||||||
}
|
|
||||||
bool isIgnoreExtension = item.IsValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(item.FilePath.ExtensionLowered);
|
|
||||||
result = GetImageProperty(metadata, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension);
|
|
||||||
if (!angleBracketCollectionAny)
|
|
||||||
_AngleBracketCollection.Clear();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -76,7 +76,7 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
System.Drawing.Size size = Stateless.Methods.ImageHelper.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
|
System.Drawing.Size size = Stateless.Methods.Dimensions.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
|
||||||
imageWidth = size.Width;
|
imageWidth = size.Width;
|
||||||
imageHeight = size.Height;
|
imageHeight = size.Height;
|
||||||
}
|
}
|
||||||
|
149
Shared/Models/Stateless/Methods/Dimensions.cs
Normal file
149
Shared/Models/Stateless/Methods/Dimensions.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
|
internal static class Dimensions
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma warning disable IDE0230
|
||||||
|
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||||
|
{
|
||||||
|
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||||
|
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||||
|
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||||
|
{ 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 },
|
||||||
|
};
|
||||||
|
#pragma warning restore IDE0230
|
||||||
|
|
||||||
|
private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < thisBytes.Count && 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? faceRight, int? faceBottom)
|
||||||
|
{
|
||||||
|
Size? result;
|
||||||
|
List<byte> magicBytes = [];
|
||||||
|
int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
|
||||||
|
if (magicBytesLengths.Length == 0)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
if (binaryReader.BaseStream.Length == binaryReader.BaseStream.Position)
|
||||||
|
_ = binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
for (int i = 0; i < magicBytesLengths[0]; i++)
|
||||||
|
{
|
||||||
|
magicBytes.Add(binaryReader.ReadByte());
|
||||||
|
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
||||||
|
{
|
||||||
|
if (StartsWith(magicBytes, kvPair.Key))
|
||||||
|
{
|
||||||
|
result = kvPair.Value(binaryReader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result is not null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result is null)
|
||||||
|
{
|
||||||
|
if (faceRight is null || faceBottom is null)
|
||||||
|
throw new Exception("face is null!");
|
||||||
|
result = new(faceRight.Value, faceBottom.Value);
|
||||||
|
}
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Size GetDimensions(string path, int? faceRight, int? faceBottom)
|
||||||
|
{
|
||||||
|
Size result;
|
||||||
|
using FileStream fileStream = File.OpenRead(path);
|
||||||
|
using BinaryReader binaryReader = new(fileStream);
|
||||||
|
result = GetDimensions(binaryReader, faceRight, faceBottom);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,132 +0,0 @@
|
|||||||
using System.Drawing;
|
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|
||||||
|
|
||||||
internal abstract class ImageHelper
|
|
||||||
{
|
|
||||||
|
|
||||||
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < thatBytes.Length; i += 1)
|
|
||||||
{
|
|
||||||
if (thisBytes[i] != thatBytes[i])
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
_ = binaryReader.ReadBytes(chunkLength - 2);
|
|
||||||
}
|
|
||||||
throw new ArgumentException("Could not recognize image format.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dimensions of an image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the image to get the dimensions of.</param>
|
|
||||||
/// <returns>The dimensions of the specified image.</returns>
|
|
||||||
/// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
|
|
||||||
internal static Size GetDimensions(BinaryReader binaryReader, int? faceRight, int? faceBottom)
|
|
||||||
{
|
|
||||||
Size? result = null;
|
|
||||||
#pragma warning disable IDE0230
|
|
||||||
Dictionary<byte[], Func<BinaryReader, Size>> _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 },
|
|
||||||
};
|
|
||||||
#pragma warning restore IDE0230
|
|
||||||
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<byte[], Func<BinaryReader, Size>> kvPair in _ImageFormatDecoders)
|
|
||||||
{
|
|
||||||
if (!StartsWith(magicBytes, kvPair.Key))
|
|
||||||
continue;
|
|
||||||
result = kvPair.Value(binaryReader);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (result is not null)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (result is null)
|
|
||||||
{
|
|
||||||
if (faceRight is null || faceBottom is null)
|
|
||||||
throw new Exception("face is null!");
|
|
||||||
result = new(faceRight.Value, faceBottom.Value);
|
|
||||||
}
|
|
||||||
return result.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dimensions of an image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the image to get the dimensions of.</param>
|
|
||||||
/// <returns>The dimensions of the specified image.</returns>
|
|
||||||
/// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
|
|
||||||
internal static Size GetDimensions(string path, int? faceRight, int? faceBottom)
|
|
||||||
{
|
|
||||||
Size result;
|
|
||||||
using BinaryReader binaryReader = new(File.OpenRead(path));
|
|
||||||
result = GetDimensions(binaryReader, faceRight, faceBottom);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Search", "Drag-Dr
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Set-Property-Item", "Drag-Drop-Set-Property-Item\Drag-Drop-Set-Property-Item.csproj", "{BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Set-Property-Item", "Drag-Drop-Set-Property-Item\Drag-Drop-Set-Property-Item.csproj", "{BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicate-Search", "Duplicate-Search\Duplicate-Search.csproj", "{48E87D9B-B802-467A-BDC7-E86F7FD01D5C}"
|
||||||
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Face", "Face\Face.csproj", "{A12E19E5-59C0-40D4-B807-DF1334D4906D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Face", "Face\Face.csproj", "{A12E19E5-59C0-40D4-B807-DF1334D4906D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceParts", "FaceParts\FaceParts.csproj", "{919525B1-60BA-40C6-BA66-6F7F4C526E01}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceParts", "FaceParts\FaceParts.csproj", "{919525B1-60BA-40C6-BA66-6F7F4C526E01}"
|
||||||
|
Reference in New Issue
Block a user