Removed Obsolete A_Property Methods
Changed GetDimensions to handle a stream at the end and one exit
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(dlibDotNet, propertyConfiguration, bMetadataSingletonDirectory, filesCollectionDirectory, keyValuePairs, splatNineIdentifiers, filePathsCollection, exifDirectoriesById, directorySearchFilter);
|
||||||
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,12 +127,12 @@ 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(IDlibDotNet dlibDotNet, 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)
|
||||||
{
|
{
|
||||||
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 };
|
||||||
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,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)
|
||||||
{
|
{
|
||||||
@ -607,7 +609,7 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
{
|
{
|
||||||
ExifDirectory? result;
|
ExifDirectory? result;
|
||||||
if (filePair.Match is null)
|
if (filePair.Match is null)
|
||||||
result = null;
|
result = Metadata.Models.Stateless.Methods.IMetadata.GetExifDirectory(filePair.FilePath);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string json = File.ReadAllText(filePair.Match.FullName);
|
string json = File.ReadAllText(filePair.Match.FullName);
|
||||||
@ -1087,7 +1089,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 +1097,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,27 +1147,22 @@ 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);
|
_ProgressBar = new(count, message, _ProgressBarOptions);
|
||||||
@ -1181,19 +1178,18 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
record.FilePathsCollection,
|
record.FilePathsCollection,
|
||||||
record.ExifDirectoriesById);
|
record.ExifDirectoriesById);
|
||||||
_ProgressBar.Dispose();
|
_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)
|
||||||
{
|
{
|
||||||
@ -1253,6 +1249,44 @@ 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;
|
||||||
@ -1279,6 +1313,8 @@ public partial class DlibDotNet : IDlibDotNet, IDisposable
|
|||||||
progressBar = new(count, message, _ProgressBarOptions);
|
progressBar = new(count, message, _ProgressBarOptions);
|
||||||
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, filePairs[i], exifDirectoriesById));
|
_ = Parallel.For(0, filePairs.Count, parallelOptions, (i, state) => ParallelFor(dlibDotNet, filePairs[i], exifDirectoriesById));
|
||||||
progressBar.Dispose();
|
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)";
|
||||||
|
@ -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