AddUserSecrets, RenameByDateTaken and BlurHash
This commit is contained in:
parent
aec9d0a55d
commit
514637b9c6
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -16,6 +16,7 @@
|
||||
"Exif",
|
||||
"Getα",
|
||||
"Greyscale",
|
||||
"Hasher",
|
||||
"jfif",
|
||||
"mmod",
|
||||
"Nicéphore",
|
||||
|
1
BlurHash.Core/.vscode/format-report.json
vendored
Normal file
1
BlurHash.Core/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
[]
|
4
BlurHash.Core/AssemblyInfo.cs
Normal file
4
BlurHash.Core/AssemblyInfo.cs
Normal file
@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("BlurHash.Core.Test")]
|
||||
[assembly: InternalsVisibleTo("Benchmarks")]
|
64
BlurHash.Core/Base83.cs
Normal file
64
BlurHash.Core/Base83.cs
Normal file
@ -0,0 +1,64 @@
|
||||
namespace BlurHash;
|
||||
|
||||
/// <summary>
|
||||
/// Contains methods to encode or decode integers to Base83-Strings
|
||||
/// </summary>
|
||||
internal static class Base83
|
||||
{
|
||||
internal const string _Charset = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~";
|
||||
|
||||
private static readonly IReadOnlyDictionary<char, int> _ReverseLookup;
|
||||
|
||||
static Base83()
|
||||
{
|
||||
// Build inverse lookup table for fast decoding
|
||||
Dictionary<char, int> charIndices = new();
|
||||
int index = 0;
|
||||
foreach (char c in _Charset)
|
||||
{
|
||||
charIndices[c] = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
_ReverseLookup = charIndices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a number into its Base83-representation
|
||||
/// </summary>
|
||||
/// <param name="number">The number to encode</param>
|
||||
/// <param name="output">The data buffer to put the result data into</param>
|
||||
/// <returns>The Base83-representation of the number</returns>
|
||||
public static void EncodeBase83(this int number, Span<char> output)
|
||||
{
|
||||
int length = output.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int digit = number % 83;
|
||||
number /= 83;
|
||||
output[length - i - 1] = _Charset[digit];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an <code>IEnumerable</code> of Base83-characters into the integral value it represents
|
||||
/// </summary>
|
||||
/// <param name="base83Data">The characters to decode</param>
|
||||
/// <returns>The decoded value as integer</returns>
|
||||
public static int DecodeBase83(this ReadOnlySpan<char> base83Data)
|
||||
{
|
||||
int result = 0;
|
||||
foreach (char c in base83Data)
|
||||
{
|
||||
if (!_ReverseLookup.TryGetValue(c, out int digit))
|
||||
{
|
||||
throw new ArgumentException("The given string contains invalid characters.", nameof(base83Data));
|
||||
}
|
||||
|
||||
result *= 83;
|
||||
result += digit;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
24
BlurHash.Core/BlurHash.Core.csproj
Normal file
24
BlurHash.Core/BlurHash.Core.csproj
Normal file
@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>library</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>BlurHash.Core</PackageId>
|
||||
<PackageVersion>2.0.0</PackageVersion>
|
||||
<Authors>Markus Palcer</Authors>
|
||||
<Description>BlurHash is a compact representation of a placeholder for an image.</Description>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<Copyright>Copyright 2019 Markus Palcer</Copyright>
|
||||
<PackageTags>blurhash image preview compression encoding</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/MarkusPalcer/blurhash.net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
</Project>
|
267
BlurHash.Core/Core.cs
Normal file
267
BlurHash.Core/Core.cs
Normal file
@ -0,0 +1,267 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace BlurHash;
|
||||
|
||||
public static class Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Encodes a 2-dimensional array of pixels into a BlurHash string
|
||||
/// </summary>
|
||||
/// <param name="pixels">The 2-dimensional array of pixels to encode</param>
|
||||
/// <param name="componentsX">The number of components used on the X-Axis for the DCT</param>
|
||||
/// <param name="componentsY">The number of components used on the Y-Axis for the DCT</param>
|
||||
/// <param name="progressCallback">An optional progress handler to receive progress updates</param>
|
||||
/// <returns>The resulting BlurHash string</returns>
|
||||
public static string Encode(Pixel[,] pixels, int componentsX, int componentsY, IProgress<int>? progressCallback = null)
|
||||
{
|
||||
if (componentsX < 1)
|
||||
throw new ArgumentException("componentsX needs to be at least 1");
|
||||
if (componentsX > 9)
|
||||
throw new ArgumentException("componentsX needs to be at most 9");
|
||||
if (componentsY < 1)
|
||||
throw new ArgumentException("componentsY needs to be at least 1");
|
||||
if (componentsY > 9)
|
||||
throw new ArgumentException("componentsY needs to be at most 9");
|
||||
|
||||
Span<Pixel> factors = stackalloc Pixel[componentsX * componentsY];
|
||||
Span<char> resultBuffer = stackalloc char[4 + 2 * componentsX * componentsY];
|
||||
|
||||
int factorCount = componentsX * componentsY;
|
||||
int processedFactors = 0;
|
||||
|
||||
int width = pixels.GetLength(0);
|
||||
int height = pixels.GetLength(1);
|
||||
|
||||
double[] xCosines = new double[width];
|
||||
double[] yCosines = new double[height];
|
||||
|
||||
for (int yComponent = 0; yComponent < componentsY; yComponent++)
|
||||
for (int xComponent = 0; xComponent < componentsX; xComponent++)
|
||||
{
|
||||
double r = 0, g = 0, b = 0;
|
||||
double normalization = (xComponent == 0 && yComponent == 0) ? 1 : 2;
|
||||
|
||||
for (int xPixel = 0; xPixel < width; xPixel++)
|
||||
{
|
||||
xCosines[xPixel] = Math.Cos(Math.PI * xComponent * xPixel / width);
|
||||
}
|
||||
|
||||
for (int yPixel = 0; yPixel < height; yPixel++)
|
||||
{
|
||||
yCosines[yPixel] = Math.Cos(Math.PI * yComponent * yPixel / height);
|
||||
}
|
||||
|
||||
for (int xPixel = 0; xPixel < width; xPixel++)
|
||||
for (int yPixel = 0; yPixel < height; yPixel++)
|
||||
{
|
||||
double basis = xCosines[xPixel] * yCosines[yPixel];
|
||||
Pixel pixel = pixels[xPixel, yPixel];
|
||||
r += basis * pixel._Red;
|
||||
g += basis * pixel._Green;
|
||||
b += basis * pixel._Blue;
|
||||
}
|
||||
|
||||
double scale = normalization / (width * height);
|
||||
factors[componentsX * yComponent + xComponent]._Red = r * scale;
|
||||
factors[componentsX * yComponent + xComponent]._Green = g * scale;
|
||||
factors[componentsX * yComponent + xComponent]._Blue = b * scale;
|
||||
|
||||
progressCallback?.Report(processedFactors * 100 / factorCount);
|
||||
processedFactors++;
|
||||
}
|
||||
|
||||
Pixel dc = factors[0];
|
||||
int acCount = componentsX * componentsY - 1;
|
||||
|
||||
int sizeFlag = componentsX - 1 + (componentsY - 1) * 9;
|
||||
sizeFlag.EncodeBase83(resultBuffer[..1]);
|
||||
|
||||
float maximumValue;
|
||||
if (acCount > 0)
|
||||
{
|
||||
// Get maximum absolute value of all AC components
|
||||
double actualMaximumValue = 0.0;
|
||||
for (int yComponent = 0; yComponent < componentsY; yComponent++)
|
||||
for (int xComponent = 0; xComponent < componentsX; xComponent++)
|
||||
{
|
||||
// Ignore DC component
|
||||
if (xComponent == 0 && yComponent == 0)
|
||||
continue;
|
||||
|
||||
int factorIndex = componentsX * yComponent + xComponent;
|
||||
|
||||
actualMaximumValue = Math.Max(Math.Abs(factors[factorIndex]._Red), actualMaximumValue);
|
||||
actualMaximumValue = Math.Max(Math.Abs(factors[factorIndex]._Green), actualMaximumValue);
|
||||
actualMaximumValue = Math.Max(Math.Abs(factors[factorIndex]._Blue), actualMaximumValue);
|
||||
}
|
||||
|
||||
int quantizedMaximumValue = (int)Math.Max(0.0, Math.Min(82.0, Math.Floor(actualMaximumValue * 166 - 0.5)));
|
||||
maximumValue = ((float)quantizedMaximumValue + 1) / 166;
|
||||
quantizedMaximumValue.EncodeBase83(resultBuffer.Slice(1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
maximumValue = 1;
|
||||
resultBuffer[1] = '0';
|
||||
}
|
||||
|
||||
EncodeDc(dc._Red, dc._Green, dc._Blue).EncodeBase83(resultBuffer.Slice(2, 4));
|
||||
|
||||
for (int yComponent = 0; yComponent < componentsY; yComponent++)
|
||||
for (int xComponent = 0; xComponent < componentsX; xComponent++)
|
||||
{
|
||||
// Ignore DC component
|
||||
if (xComponent == 0 && yComponent == 0)
|
||||
continue;
|
||||
|
||||
int factorIndex = componentsX * yComponent + xComponent;
|
||||
|
||||
EncodeAc(factors[factorIndex]._Red, factors[factorIndex]._Green, factors[factorIndex]._Blue, maximumValue).EncodeBase83(resultBuffer.Slice(6 + (factorIndex - 1) * 2, 2));
|
||||
}
|
||||
|
||||
return resultBuffer.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BlurHash string into a 2-dimensional array of pixels
|
||||
/// </summary>
|
||||
/// <param name="blurhash">The blurhash string to decode</param>
|
||||
/// <param name="pixels">
|
||||
/// A two-dimensional array that will be filled with the pixel data.<br />
|
||||
/// First dimension is the width, second dimension is the height
|
||||
/// </param>
|
||||
/// <param name="punch">A value that affects the contrast of the decoded image. 1 means normal, smaller values will make the effect more subtle, and larger values will make it stronger.</param>
|
||||
/// <param name="progressCallback">An optional progress handler to receive progress updates</param>
|
||||
/// <returns>A 2-dimensional array of <see cref="Pixel"/>s </returns>
|
||||
public static void Decode(string blurhash, Pixel[,] pixels, double punch = 1.0, IProgress<int>? progressCallback = null)
|
||||
{
|
||||
if (blurhash.Length < 6)
|
||||
{
|
||||
throw new ArgumentException("BlurHash value needs to be at least 6 characters", nameof(blurhash));
|
||||
}
|
||||
|
||||
ReadOnlySpan<char> blurhashSpan = blurhash.AsSpan();
|
||||
|
||||
int outputWidth = pixels.GetLength(0);
|
||||
int outputHeight = pixels.GetLength(1);
|
||||
|
||||
int sizeFlag = blurhashSpan[..1].DecodeBase83();
|
||||
|
||||
int componentsY = sizeFlag / 9 + 1;
|
||||
int componentsX = sizeFlag % 9 + 1;
|
||||
int componentCount = componentsX * componentsY;
|
||||
|
||||
if (blurhash.Length != 4 + 2 * componentsX * componentsY)
|
||||
{
|
||||
throw new ArgumentException("BlurHash value is missing data", nameof(blurhash));
|
||||
}
|
||||
|
||||
double quantizedMaximumValue = blurhashSpan.Slice(1, 1).DecodeBase83();
|
||||
double maximumValue = (quantizedMaximumValue + 1.0) / 166.0;
|
||||
|
||||
Pixel[,] coefficients = new Pixel[componentsX, componentsY];
|
||||
|
||||
int componentIndex = 0;
|
||||
for (int yComponent = 0; yComponent < componentsY; yComponent++)
|
||||
for (int xComponent = 0; xComponent < componentsX; xComponent++)
|
||||
{
|
||||
if (xComponent == 0 && yComponent == 0)
|
||||
{
|
||||
int value = blurhashSpan.Slice(2, 4).DecodeBase83();
|
||||
coefficients[xComponent, yComponent] = DecodeDc(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int value = blurhashSpan.Slice(4 + componentIndex * 2, 2).DecodeBase83();
|
||||
coefficients[xComponent, yComponent] = DecodeAc(value, maximumValue * punch);
|
||||
}
|
||||
|
||||
componentIndex++;
|
||||
}
|
||||
|
||||
for (int xPixel = 0; xPixel < outputWidth; xPixel++)
|
||||
for (int yPixel = 0; yPixel < outputHeight; yPixel++)
|
||||
{
|
||||
ref Pixel result = ref pixels[xPixel, yPixel];
|
||||
|
||||
result._Red = 0.0;
|
||||
result._Green = 0.0;
|
||||
result._Blue = 0.0;
|
||||
}
|
||||
|
||||
double[] xCosines = new double[outputWidth];
|
||||
double[] yCosines = new double[outputHeight];
|
||||
|
||||
componentIndex = 1;
|
||||
for (int componentX = 0; componentX < componentsX; componentX++)
|
||||
for (int componentY = 0; componentY < componentsY; componentY++)
|
||||
{
|
||||
for (int xPixel = 0; xPixel < outputWidth; xPixel++)
|
||||
{
|
||||
xCosines[xPixel] = Math.Cos(Math.PI * xPixel * componentX / outputWidth);
|
||||
}
|
||||
|
||||
for (int yPixel = 0; yPixel < outputHeight; yPixel++)
|
||||
{
|
||||
yCosines[yPixel] = Math.Cos(Math.PI * yPixel * componentY / outputHeight);
|
||||
}
|
||||
|
||||
Pixel coefficient = coefficients[componentX, componentY];
|
||||
|
||||
for (int xPixel = 0; xPixel < outputWidth; xPixel++)
|
||||
for (int yPixel = 0; yPixel < outputHeight; yPixel++)
|
||||
{
|
||||
ref Pixel result = ref pixels[xPixel, yPixel];
|
||||
|
||||
double basis = xCosines[xPixel] * yCosines[yPixel];
|
||||
|
||||
result._Red += coefficient._Red * basis;
|
||||
result._Green += coefficient._Green * basis;
|
||||
result._Blue += coefficient._Blue * basis;
|
||||
}
|
||||
|
||||
progressCallback?.Report(componentIndex * 100 / componentCount);
|
||||
componentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
private static int EncodeAc(double r, double g, double b, double maximumValue)
|
||||
{
|
||||
int quantizedR = (int)Math.Max(0, Math.Min(18, Math.Floor(MathUtils.SignPow(r / maximumValue, 0.5) * 9 + 9.5)));
|
||||
int quantizedG = (int)Math.Max(0, Math.Min(18, Math.Floor(MathUtils.SignPow(g / maximumValue, 0.5) * 9 + 9.5)));
|
||||
int quantizedB = (int)Math.Max(0, Math.Min(18, Math.Floor(MathUtils.SignPow(b / maximumValue, 0.5) * 9 + 9.5)));
|
||||
|
||||
return quantizedR * 19 * 19 + quantizedG * 19 + quantizedB;
|
||||
}
|
||||
|
||||
private static int EncodeDc(double r, double g, double b)
|
||||
{
|
||||
int roundedR = MathUtils.LinearTosRgb(r);
|
||||
int roundedG = MathUtils.LinearTosRgb(g);
|
||||
int roundedB = MathUtils.LinearTosRgb(b);
|
||||
return (roundedR << 16) + (roundedG << 8) + roundedB;
|
||||
}
|
||||
|
||||
private static Pixel DecodeDc(BigInteger value)
|
||||
{
|
||||
int intR = (int)value >> 16;
|
||||
int intG = (int)(value >> 8) & 255;
|
||||
int intB = (int)value & 255;
|
||||
return new Pixel(MathUtils.SRgbToLinear(intR), MathUtils.SRgbToLinear(intG), MathUtils.SRgbToLinear(intB));
|
||||
}
|
||||
|
||||
private static Pixel DecodeAc(BigInteger value, double maximumValue)
|
||||
{
|
||||
double quantizedR = (double)(value / (19 * 19));
|
||||
double quantizedG = (double)(value / 19 % 19);
|
||||
double quantizedB = (double)(value % 19);
|
||||
|
||||
Pixel result = new(
|
||||
MathUtils.SignPow((quantizedR - 9.0) / 9.0, 2.0) * maximumValue,
|
||||
MathUtils.SignPow((quantizedG - 9.0) / 9.0, 2.0) * maximumValue,
|
||||
MathUtils.SignPow((quantizedB - 9.0) / 9.0, 2.0) * maximumValue
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
38
BlurHash.Core/MathUtils.cs
Normal file
38
BlurHash.Core/MathUtils.cs
Normal file
@ -0,0 +1,38 @@
|
||||
namespace BlurHash;
|
||||
|
||||
/// <summary>
|
||||
/// Utility methods for mathematical calculations
|
||||
/// </summary>
|
||||
public static class MathUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates <c>Math.Pow(base, exponent)</c> but retains the sign of <c>base</c> in the result.
|
||||
/// </summary>
|
||||
/// <param name="base">The base of the power. The sign of this value will be the sign of the result</param>
|
||||
/// <param name="exponent">The exponent of the power</param>
|
||||
public static double SignPow(double @base, double exponent) => Math.Sign(@base) * Math.Pow(Math.Abs(@base), exponent);
|
||||
|
||||
/// <summary>
|
||||
/// Converts an sRGB input value (0 to 255) into a linear double value
|
||||
/// </summary>
|
||||
public static double SRgbToLinear(int value)
|
||||
{
|
||||
double v = value / 255.0;
|
||||
if (v <= 0.04045)
|
||||
return v / 12.92;
|
||||
else
|
||||
return Math.Pow((v + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a linear double value into an sRGB input value (0 to 255)
|
||||
/// </summary>
|
||||
public static int LinearTosRgb(double value)
|
||||
{
|
||||
double v = Math.Max(0.0, Math.Min(1.0, value));
|
||||
if (v <= 0.0031308)
|
||||
return (int)(v * 12.92 * 255 + 0.5);
|
||||
else
|
||||
return (int)((1.055 * Math.Pow(v, 1 / 2.4) - 0.055) * 255 + 0.5);
|
||||
}
|
||||
}
|
18
BlurHash.Core/Pixel.cs
Normal file
18
BlurHash.Core/Pixel.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace BlurHash;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a pixel within the BlurHash algorithm
|
||||
/// </summary>
|
||||
public struct Pixel
|
||||
{
|
||||
public double _Red;
|
||||
public double _Green;
|
||||
public double _Blue;
|
||||
|
||||
public Pixel(double red, double green, double blue)
|
||||
{
|
||||
_Red = red;
|
||||
_Green = green;
|
||||
_Blue = blue;
|
||||
}
|
||||
}
|
1
BlurHash.System.Drawing.Common/.vscode/format-report.json
vendored
Normal file
1
BlurHash.System.Drawing.Common/.vscode/format-report.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
[]
|
4
BlurHash.System.Drawing.Common/AssemblyInfo.cs
Normal file
4
BlurHash.System.Drawing.Common/AssemblyInfo.cs
Normal file
@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("BlurHash.System.Drawing.Common.Test")]
|
||||
[assembly: InternalsVisibleTo("Benchmarks")]
|
@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>library</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>BlurHash.System.Drawing.Common</PackageId>
|
||||
<PackageVersion>3.0.0</PackageVersion>
|
||||
<Authors>Markus Palcer</Authors>
|
||||
<Description>BlurHash is a compact representation of a placeholder for an image.</Description>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<Copyright>Copyright 2019 Markus Palcer</Copyright>
|
||||
<PackageTags>blurhash image preview compression encoding</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/MarkusPalcer/blurhash.net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlurHash.Core\BlurHash.Core.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
110
BlurHash.System.Drawing.Common/BlurHasher.cs
Normal file
110
BlurHash.System.Drawing.Common/BlurHasher.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using BlurHash;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace System.Drawing.BlurHash;
|
||||
|
||||
public static class BlurHasher
|
||||
{
|
||||
|
||||
#pragma warning disable CA1416
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a picture into a BlurHash string
|
||||
/// </summary>
|
||||
/// <param name="image">The picture to encode</param>
|
||||
/// <param name="componentsX">The number of components used on the X-Axis for the DCT</param>
|
||||
/// <param name="componentsY">The number of components used on the Y-Axis for the DCT</param>
|
||||
/// <returns>The resulting BlurHash string</returns>
|
||||
public static string Encode(Image image, int componentsX, int componentsY) => Core.Encode(ConvertBitmap(image as Bitmap ?? new Bitmap(image)), componentsX, componentsY);
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BlurHash string into a <c>System.Drawing.Image</c>
|
||||
/// </summary>
|
||||
/// <param name="blurhash">The blurhash string to decode</param>
|
||||
/// <param name="outputWidth">The desired width of the output in pixels</param>
|
||||
/// <param name="outputHeight">The desired height of the output in pixels</param>
|
||||
/// <param name="punch">A value that affects the contrast of the decoded image. 1 means normal, smaller values will make the effect more subtle, and larger values will make it stronger.</param>
|
||||
/// <returns>The decoded preview</returns>
|
||||
public static Image Decode(string blurhash, int outputWidth, int outputHeight, double punch = 1.0)
|
||||
{
|
||||
Pixel[,] pixelData = new Pixel[outputWidth, outputHeight];
|
||||
Core.Decode(blurhash, pixelData, punch);
|
||||
return ConvertToBitmap(pixelData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given bitmap to the library-independent representation used within the BlurHash-core
|
||||
/// </summary>
|
||||
/// <param name="sourceBitmap">The bitmap to encode</param>
|
||||
public static unsafe Pixel[,] ConvertBitmap(Image sourceBitmap)
|
||||
{
|
||||
int width = sourceBitmap.Width;
|
||||
int height = sourceBitmap.Height;
|
||||
|
||||
using Bitmap temporaryBitmap = new(width, height, PixelFormat.Format24bppRgb);
|
||||
using (Graphics graphics = Graphics.FromImage(temporaryBitmap))
|
||||
{
|
||||
graphics.DrawImageUnscaled(sourceBitmap, 0, 0);
|
||||
}
|
||||
|
||||
// Lock the bitmap's bits.
|
||||
BitmapData bmpData = temporaryBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, temporaryBitmap.PixelFormat);
|
||||
|
||||
// Get the address of the first line.
|
||||
nint ptr = bmpData.Scan0;
|
||||
|
||||
Pixel[,] result = new Pixel[width, height];
|
||||
|
||||
byte* rgb = (byte*)ptr.ToPointer();
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int index = bmpData.Stride * y;
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
ref Pixel res = ref result[x, y];
|
||||
res._Blue = MathUtils.SRgbToLinear(rgb[index++]);
|
||||
res._Green = MathUtils.SRgbToLinear(rgb[index++]);
|
||||
res._Red = MathUtils.SRgbToLinear(rgb[index++]);
|
||||
}
|
||||
}
|
||||
|
||||
temporaryBitmap.UnlockBits(bmpData);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the library-independent representation of pixels into a bitmap
|
||||
/// </summary>
|
||||
/// <param name="pixelData">The library-independent representation of the image</param>
|
||||
/// <returns>A <c>System.Drawing.Bitmap</c> in 32bpp-RGB representation</returns>
|
||||
public static unsafe Bitmap ConvertToBitmap(Pixel[,] pixelData)
|
||||
{
|
||||
int width = pixelData.GetLength(0);
|
||||
int height = pixelData.GetLength(1);
|
||||
|
||||
byte[] data = new byte[width * height * 4];
|
||||
|
||||
int index = 0;
|
||||
for (int yPixel = 0; yPixel < height; yPixel++)
|
||||
for (int xPixel = 0; xPixel < width; xPixel++)
|
||||
{
|
||||
Pixel pixel = pixelData[xPixel, yPixel];
|
||||
|
||||
data[index++] = (byte)MathUtils.LinearTosRgb(pixel._Blue);
|
||||
data[index++] = (byte)MathUtils.LinearTosRgb(pixel._Green);
|
||||
data[index++] = (byte)MathUtils.LinearTosRgb(pixel._Red);
|
||||
data[index++] = 0;
|
||||
}
|
||||
|
||||
Bitmap bmp;
|
||||
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
bmp = new Bitmap(width, height, width * 4, PixelFormat.Format32bppRgb, new IntPtr(ptr));
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
}
|
45
BlurHash/BlurHash.csproj
Normal file
45
BlurHash/BlurHash.csproj
Normal file
@ -0,0 +1,45 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>library</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>Phares.View.by.Distance.BlurHash</PackageId>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<Version>7.0.101.1</Version>
|
||||
<Authors>Mike Phares</Authors>
|
||||
<Company>Phares</Company>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
|
||||
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
|
||||
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsWindows)'=='true'">
|
||||
<DefineConstants>Windows</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsOSX)'=='true'">
|
||||
<DefineConstants>OSX</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsLinux)'=='true'">
|
||||
<DefineConstants>Linux</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
<ProjectReference Include="..\BlurHash.System.Drawing.Common\BlurHash.System.Drawing.Common.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
52
BlurHash/Models/BlurHasher.cs
Normal file
52
BlurHash/Models/BlurHasher.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
namespace View_by_Distance.BlurHash.Models;
|
||||
|
||||
public class BlurHasher : IBlurHasher
|
||||
{
|
||||
|
||||
string IBlurHasher.Encode(Image image) =>
|
||||
#pragma warning disable CA1416
|
||||
image.Width < image.Height ? Encode(image, 4, 3) : Encode(image, 3, 4);
|
||||
#pragma warning restore CA1416
|
||||
|
||||
string IBlurHasher.EncodeAndSave(Image image, string directory) =>
|
||||
#pragma warning disable CA1416
|
||||
image.Width < image.Height ? EncodeAndSave(image, 4, 3, 300, 190, directory) : EncodeAndSave(image, 3, 4, 300, 190, directory);
|
||||
#pragma warning restore CA1416
|
||||
|
||||
string IBlurHasher.Encode(Image image, int x, int y) =>
|
||||
Encode(image, x, y);
|
||||
|
||||
string IBlurHasher.EncodeAndSave(Image image, int x, int y, string directory) =>
|
||||
EncodeAndSave(image, x, y, 300, 190, directory);
|
||||
|
||||
internal static string Encode(Image image, int x, int y) =>
|
||||
System.Drawing.BlurHash.BlurHasher.Encode(image, x, y);
|
||||
|
||||
public string EncodeAndSave(Image image, int x, int y, int width, int height, string directory)
|
||||
{
|
||||
string result;
|
||||
int actualByte;
|
||||
result = System.Drawing.BlurHash.BlurHasher.Encode(image, x, y);
|
||||
byte[] blurHashBytes = Encoding.UTF8.GetBytes(result);
|
||||
using Bitmap actualImage = (Bitmap)System.Drawing.BlurHash.BlurHasher.Decode(result, width, height);
|
||||
string joined = string.Join(string.Empty, blurHashBytes.Select(l => l.ToString("000")));
|
||||
string fileName = Path.Combine(directory, $"{x}x{y}-{width}x{height}-{joined}.png");
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
using FileStream fileStream = new(fileName, FileMode.CreateNew);
|
||||
#pragma warning disable CA1416
|
||||
actualImage.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
|
||||
#pragma warning restore CA1416
|
||||
_ = fileStream.Seek(0, SeekOrigin.Begin);
|
||||
actualByte = fileStream.ReadByte();
|
||||
while (actualByte > -1)
|
||||
actualByte = fileStream.ReadByte();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -19,7 +19,8 @@ public class Program
|
||||
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
16
Date-Group/.vscode/UserSecrets/secrets.json
vendored
Normal file
16
Date-Group/.vscode/UserSecrets/secrets.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"_Application": "Date-Group",
|
||||
"Windows": {
|
||||
"Configuration": {
|
||||
"xByHash": false,
|
||||
"ByHash": true,
|
||||
"xPopulatePropertyId": false,
|
||||
"PopulatePropertyId": true,
|
||||
"RootDirectory": "D:/Tmp/phares/Pictures",
|
||||
"xxRootDirectory": "C:/Tmp/Phares/Compare/Images-1e85c0ba",
|
||||
"xxxRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-1e85c0ba",
|
||||
"xxxxRootDirectory": "C:/Tmp/Phares/Compare/Not-Copy-Copy-1e85c0ba",
|
||||
"xxxxxRootDirectory": "F:/Tmp/Phares/2022-11-03-DCIM/DCIM/100D3400 2022"
|
||||
}
|
||||
}
|
||||
}
|
86
Date-Group/.vscode/tasks.json
vendored
86
Date-Group/.vscode/tasks.json
vendored
@ -1,38 +1,72 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"options": {
|
||||
"env": {
|
||||
"serverUserSecretsId": "8004d966-1a9e-4545-a220-83f32b6a13e9"
|
||||
}
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"label": "userSecretsInit",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/Date-Group.csproj",
|
||||
"init"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "userSecretsSet",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/Date-Group.csproj",
|
||||
"set",
|
||||
"SaveDirectory",
|
||||
"D:/1) Images A/Images-1e85c0ba-Results/A2) People/1e85c0ba/([])"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "userSecretsMkLink",
|
||||
"command": "cmd",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"/c",
|
||||
"mklink",
|
||||
"/J",
|
||||
".vscode\\UserSecrets",
|
||||
"${userHome}\\AppData\\Roaming\\Microsoft\\UserSecrets\\$env:serverUserSecretsId"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "format",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"format",
|
||||
"--report",
|
||||
".vscode",
|
||||
"--verbosity",
|
||||
"detailed",
|
||||
"--severity",
|
||||
"warn"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Date-Group.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Date-Group.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/Date-Group.csproj",
|
||||
"${workspaceFolder}/View-by-Distance-MKLink-Console.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
|
@ -6,7 +6,8 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<UserSecretsId>8004d966-1a9e-4545-a220-83f32b6a13e9</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>Phares.View.by.Distance.Date.Group</PackageId>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
@ -38,8 +39,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
@ -49,6 +50,7 @@
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
<ProjectReference Include="..\Property\Property.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -65,7 +65,8 @@ public class DateGroup
|
||||
throw new Exception();
|
||||
if (propertyConfiguration.PopulatePropertyId && (configuration.ByCreateDateShortcut || configuration.ByHash) && Shared.Models.Stateless.Methods.IProperty.Any(containers))
|
||||
{
|
||||
propertyLogic.SavePropertyParallelWork(ticks, t, containers);
|
||||
IBlurHasher? blurHasher = new BlurHash.Models.BlurHasher();
|
||||
propertyLogic.SavePropertyParallelWork(ticks, t, containers, blurHasher);
|
||||
if (appSettings.MaxDegreeOfParallelism < 2)
|
||||
ticks = LogDelta(ticks, nameof(A_Property.SavePropertyParallelWork));
|
||||
if (propertyLogic.ExceptionsDirectories.Any())
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -4,22 +4,7 @@
|
||||
"Log4netProvider": "Debug"
|
||||
}
|
||||
},
|
||||
"MaxDegreeOfParallelism": 6,
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Debug"
|
||||
},
|
||||
"Windows": {
|
||||
"Configuration": {
|
||||
"xByHash": false,
|
||||
"ByHash": true,
|
||||
"xPopulatePropertyId": false,
|
||||
"PopulatePropertyId": true,
|
||||
"xRootDirectory": "C:/Tmp/phares/Pictures",
|
||||
"xxRootDirectory": "C:/Tmp/Phares/Compare/Images-1e85c0ba",
|
||||
"xxxRootDirectory": "F:/Tmp/Phares/Compare/Not-Copy-Copy-1e85c0ba",
|
||||
"xxxxRootDirectory": "C:/Tmp/Phares/Compare/Not-Copy-Copy-1e85c0ba",
|
||||
"xxxxxRootDirectory": "F:/Tmp/Phares/2022-11-03-DCIM/DCIM/100D3400 2022",
|
||||
"RootDirectory": "D:/1) Images A/Images-1e85c0ba/_"
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -38,7 +38,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -35,7 +35,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
|
@ -30,7 +30,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -40,7 +40,8 @@ public partial class DragDropExplorer : Form
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
configurationRoot = configurationBuilder.Build();
|
||||
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace View_by_Distance.Drag_Drop_Explorer;
|
||||
|
||||
static class Program
|
||||
public class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
|
@ -30,7 +30,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -39,7 +39,8 @@ public partial class DragDropMove : Form
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
configurationRoot = configurationBuilder.Build();
|
||||
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
|
||||
@ -201,10 +202,11 @@ public partial class DragDropMove : Form
|
||||
List<(string, int, DateTime)> results = new();
|
||||
DateTime dateTime;
|
||||
Shared.Models.Property property;
|
||||
Shared.Models.Methods.IBlurHasher? blurHasher = null;
|
||||
string[] files = Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
foreach (string file in files)
|
||||
{
|
||||
property = Property.Models.A_Property.GetImageProperty(file);
|
||||
property = Property.Models.A_Property.GetImageProperty(blurHasher, file);
|
||||
if (property.Id is null || property.DateTimeOriginal is null)
|
||||
continue;
|
||||
dateTime = property.DateTimeOriginal.Value.AddTicks(ticks);
|
||||
@ -238,6 +240,7 @@ public partial class DragDropMove : Form
|
||||
ticks++;
|
||||
|
||||
}
|
||||
Shared.Models.Methods.IBlurHasher? blurHasher = null;
|
||||
List<(string, int, DateTime)> collection = GetCollection(checkDirectory, minimumDateTime, maximumDateTime, ticks);
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
|
||||
foreach ((string file, int id, DateTime dateTime) in collection)
|
||||
@ -252,7 +255,7 @@ public partial class DragDropMove : Form
|
||||
bitmap.SetPropertyItem(propertyItem);
|
||||
bitmap.Save(checkFile);
|
||||
bitmap.Dispose();
|
||||
property = Property.Models.A_Property.GetImageProperty(checkFile);
|
||||
property = Property.Models.A_Property.GetImageProperty(blurHasher, checkFile);
|
||||
if (property.Id is null || property.Id.Value != id)
|
||||
throw new Exception();
|
||||
}
|
||||
@ -287,10 +290,11 @@ public partial class DragDropMove : Form
|
||||
_Logger.Error("bad file(s) or target file(s) or maximum directory doesn't equal 1!");
|
||||
else
|
||||
{
|
||||
Shared.Models.Methods.IBlurHasher? blurHasher = null;
|
||||
DateTime minimumDateTime = DateTime.ParseExact(Path.GetFileName(minimumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None);
|
||||
DateTime maximumDateTime = DateTime.ParseExact(Path.GetFileName(maximumDirectory.First()), format, null, System.Globalization.DateTimeStyles.None).AddHours(23);
|
||||
Shared.Models.Property badProperty = Property.Models.A_Property.GetImageProperty(badFiles.First());
|
||||
Shared.Models.Property targetProperty = Property.Models.A_Property.GetImageProperty(targetFiles.First());
|
||||
Shared.Models.Property badProperty = Property.Models.A_Property.GetImageProperty(blurHasher, badFiles.First());
|
||||
Shared.Models.Property targetProperty = Property.Models.A_Property.GetImageProperty(blurHasher, targetFiles.First());
|
||||
if (badProperty.DateTimeOriginal is null || targetProperty.DateTimeOriginal is null)
|
||||
_Logger.Error("Date is null!");
|
||||
else
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace View_by_Distance.Drag_Drop_Explorer;
|
||||
|
||||
static class Program
|
||||
public class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
|
@ -30,7 +30,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -44,7 +44,8 @@ public partial class DragDropSearch : Form
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
configurationRoot = configurationBuilder.Build();
|
||||
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
|
||||
|
@ -2,7 +2,7 @@ using View_by_Distance.Shared.Models;
|
||||
|
||||
namespace View_by_Distance.Drag_Drop;
|
||||
|
||||
static class Program
|
||||
public class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
|
@ -38,7 +38,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -2,7 +2,9 @@
|
||||
using Phares.Shared;
|
||||
using ShellProgressBar;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using View_by_Distance.Distance.Models;
|
||||
using View_by_Distance.Face.Models;
|
||||
@ -30,6 +32,7 @@ public partial class DlibDotNet
|
||||
private readonly Serilog.ILogger? _Log;
|
||||
private readonly D2_FaceParts _FaceParts;
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly IBlurHasher _IBlurHasher;
|
||||
private readonly List<string> _Exceptions;
|
||||
private readonly IsEnvironment _IsEnvironment;
|
||||
private readonly bool _PropertyRootExistedBefore;
|
||||
@ -56,6 +59,7 @@ public partial class DlibDotNet
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
_Exceptions = new List<string>();
|
||||
_Log = Serilog.Log.ForContext<DlibDotNet>();
|
||||
_IBlurHasher = new BlurHash.Models.BlurHasher();
|
||||
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
|
||||
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
|
||||
_Log.Information(propertyConfiguration.RootDirectory);
|
||||
@ -367,12 +371,37 @@ public partial class DlibDotNet
|
||||
if (_Log is null)
|
||||
throw new NullReferenceException(nameof(_Log));
|
||||
List<Shared.Models.Face> faces;
|
||||
Shared.Models.Property property;
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
DateTime dateTime = DateTime.Now;
|
||||
Shared.Models.Property? property;
|
||||
List<string> parseExceptions = new();
|
||||
List<Tuple<string, DateTime>> subFileTuples = new();
|
||||
List<KeyValuePair<string, string>> metadataCollection;
|
||||
if (item.Property is not null && item.Property.Id is not null && !item.Any() && item.Property.BlurHash is null)
|
||||
{
|
||||
(string aResultsFullGroupDirectory, _) = GetResultsFullGroupDirectories();
|
||||
string aPropertySingletonDirectory = Path.Combine(aResultsFullGroupDirectory, "{}");
|
||||
string[] files = Directory.GetFiles(aPropertySingletonDirectory, $"{item.Property.Id.Value}*", SearchOption.AllDirectories);
|
||||
if (files.Length == 1)
|
||||
{
|
||||
string matchFile = files.First();
|
||||
string json = File.ReadAllText(matchFile);
|
||||
string find = "\"CreationTime\":";
|
||||
if (!json.Contains(find))
|
||||
throw new NotImplementedException();
|
||||
#pragma warning disable CA1416
|
||||
using Image image = Image.FromFile(item.ImageFileHolder.FullName);
|
||||
#pragma warning restore CA1416
|
||||
string blurHash = _IBlurHasher.Encode(image);
|
||||
json = json.Replace(find, $"\"{nameof(item.Property.BlurHash)}\": \"{blurHash}\", {find}");
|
||||
property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
|
||||
if (property is null || property.BlurHash is null)
|
||||
throw new NullReferenceException(nameof(property));
|
||||
json = JsonSerializer.Serialize(property, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(matchFile, json);
|
||||
File.SetLastWriteTime(matchFile, item.Property.LastWriteTime);
|
||||
}
|
||||
}
|
||||
if (item.Property is not null && item.Property.Id is not null && !item.Any())
|
||||
{
|
||||
property = item.Property;
|
||||
@ -398,7 +427,7 @@ public partial class DlibDotNet
|
||||
_Log.Information(string.Concat("LastWriteTimeChanged <", item.ImageFileHolder.FullName, '>'));
|
||||
else if (item.Moved.HasValue && item.Moved.Value)
|
||||
_Log.Information(string.Concat("Moved <", item.ImageFileHolder.FullName, '>'));
|
||||
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
|
||||
property = propertyLogic.GetProperty(_IBlurHasher, item, subFileTuples, parseExceptions);
|
||||
item.Update(property);
|
||||
if (propertyHashCode is null)
|
||||
{
|
||||
@ -1134,7 +1163,7 @@ public partial class DlibDotNet
|
||||
List<Shared.Models.Face> distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems);
|
||||
Mapping[] distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, containers, mapLogic, distinctItems: true);
|
||||
int totalNotMapped = mapLogic.UpdateMappingFromPerson(distinctFilteredMappingCollection);
|
||||
string json = System.Text.Json.JsonSerializer.Serialize(distinctFilteredMappingCollection);
|
||||
string json = JsonSerializer.Serialize(distinctFilteredMappingCollection);
|
||||
File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json);
|
||||
for (int i = 1; i < 5; i++)
|
||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
|
||||
|
@ -40,8 +40,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
@ -49,6 +49,7 @@
|
||||
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
|
||||
<ProjectReference Include="..\FaceRecognitionDotNet\FaceRecognitionDotNet.csproj" />
|
||||
<ProjectReference Include="..\Distance\Distance.csproj" />
|
||||
<ProjectReference Include="..\Face\Face.csproj" />
|
||||
|
@ -19,7 +19,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -35,7 +35,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
|
||||
|
@ -34,7 +34,7 @@
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
@ -38,7 +38,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
@ -39,7 +39,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -35,7 +35,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="WindowsShortcutFactory" Version="1.1.0" />
|
||||
|
@ -37,12 +37,12 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -102,7 +102,7 @@ public class A_Property
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Shared.Models.Property GetImageProperty(FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, ASCIIEncoding asciiEncoding, bool writeBitmapDataBytes, string? angleBracket)
|
||||
private static Shared.Models.Property GetImageProperty(Shared.Models.Methods.IBlurHasher? blurHasher, FileHolder fileHolder, Shared.Models.Property? property, bool populateId, bool isIgnoreExtension, bool isValidImageFormatExtension, bool isValidMetadataExtensions, int? id, ASCIIEncoding asciiEncoding, bool writeBitmapDataBytes, string? angleBracket)
|
||||
{
|
||||
Shared.Models.Property result;
|
||||
byte[] bytes;
|
||||
@ -114,6 +114,7 @@ public class A_Property
|
||||
string? model = null;
|
||||
string dateTimeFormat;
|
||||
DateTime checkDateTime;
|
||||
string? blurHash = null;
|
||||
DateTime? dateTime = null;
|
||||
PropertyItem? propertyItem;
|
||||
string? orientation = null;
|
||||
@ -150,6 +151,16 @@ public class A_Property
|
||||
File.WriteAllBytes(Path.ChangeExtension(contentFileInfo.FullName, string.Empty), bytes);
|
||||
}
|
||||
}
|
||||
if (blurHasher is not null && property?.BlurHash is null)
|
||||
{
|
||||
if (angleBracket is null)
|
||||
blurHash = blurHasher.Encode(image);
|
||||
else
|
||||
{
|
||||
string blurHashDirectory = angleBracket.Replace("<>", "()");
|
||||
blurHash = blurHasher.EncodeAndSave(image, blurHashDirectory);
|
||||
}
|
||||
}
|
||||
width = image.Width;
|
||||
height = image.Height;
|
||||
dateTimeFormat = Shared.Models.Stateless.Methods.IProperty.DateTimeFormat();
|
||||
@ -242,15 +253,15 @@ public class A_Property
|
||||
if (fileHolder.LastWriteTime is null && property?.LastWriteTime is null)
|
||||
throw new NullReferenceException(nameof(fileHolder.LastWriteTime));
|
||||
if (fileHolder.CreationTime is not null && fileHolder.LastWriteTime is not null)
|
||||
result = new(fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, fileHolder.LastWriteTime.Value, make, model, orientation, width);
|
||||
result = new(blurHash, fileHolder.CreationTime.Value, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, fileHolder.LastWriteTime.Value, make, model, orientation, width);
|
||||
else if (property is not null)
|
||||
result = new(property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, property.LastWriteTime, make, model, orientation, width);
|
||||
result = new(blurHash, property.CreationTime, dateTime, dateTimeDigitized, dateTimeFromName, dateTimeOriginal, fileLength, gpsDateStamp, height, id, property.LastWriteTime, make, model, orientation, width);
|
||||
else
|
||||
throw new NullReferenceException(nameof(property));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Shared.Models.Property GetImageProperty(string fileName)
|
||||
public static Shared.Models.Property GetImageProperty(Shared.Models.Methods.IBlurHasher? blurHasher, string fileName)
|
||||
{
|
||||
int? id = null;
|
||||
bool populateId = true;
|
||||
@ -262,18 +273,18 @@ public class A_Property
|
||||
FileHolder fileHolder = new(fileName);
|
||||
bool isValidImageFormatExtension = true;
|
||||
Shared.Models.Property? property = null;
|
||||
Shared.Models.Property result = GetImageProperty(fileHolder, property, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, asciiEncoding, writeBitmapDataBytes, angleBracket);
|
||||
Shared.Models.Property result = GetImageProperty(blurHasher, fileHolder, property, populateId, isIgnoreExtension, isValidImageFormatExtension, isValidMetadataExtensions, id, asciiEncoding, writeBitmapDataBytes, angleBracket);
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416
|
||||
|
||||
private Shared.Models.Property GetPropertyOfPrivate(Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidMetadataExtensions)
|
||||
private Shared.Models.Property GetPropertyOfPrivate(Shared.Models.Methods.IBlurHasher? blurHasher, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions, bool isIgnoreExtension, bool isValidMetadataExtensions)
|
||||
{
|
||||
Shared.Models.Property? result;
|
||||
string json;
|
||||
int? id = null;
|
||||
FileInfo fileInfo;
|
||||
string? json = null;
|
||||
bool hasWrongYearProperty = false;
|
||||
string[] changesFrom = Array.Empty<string>();
|
||||
string angleBracket = _AngleBracketCollection[0];
|
||||
@ -356,10 +367,28 @@ public class A_Property
|
||||
parseExceptions.Add(nameof(A_Property));
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(json) && result is not null && blurHasher is not null && result.BlurHash is null)
|
||||
{
|
||||
string find = "\"CreationTime\":";
|
||||
if (!json.Contains(find))
|
||||
throw new NotImplementedException();
|
||||
string blurHashDirectory = angleBracket.Replace("<>", "()");
|
||||
#pragma warning disable CA1416
|
||||
using Image image = Image.FromFile(item.ImageFileHolder.FullName);
|
||||
#pragma warning restore CA1416
|
||||
string blurHash = blurHasher.EncodeAndSave(image, blurHashDirectory);
|
||||
json = json.Replace(find, $"\"{nameof(result.BlurHash)}\": \"{blurHash}\", {find}");
|
||||
result = JsonSerializer.Deserialize<Shared.Models.Property>(json);
|
||||
if (result is null || result.BlurHash is null)
|
||||
throw new NullReferenceException(nameof(result));
|
||||
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
|
||||
File.WriteAllText(fileInfo.FullName, json);
|
||||
File.SetLastWriteTime(fileInfo.FullName, fileInfo.LastWriteTime);
|
||||
}
|
||||
if (result is null)
|
||||
{
|
||||
id ??= item.ImageFileHolder.Id;
|
||||
result = GetImageProperty(item.ImageFileHolder, result, populateId, isIgnoreExtension, item.IsValidImageFormatExtension, isValidMetadataExtensions, id, _ASCIIEncoding, _Configuration.WriteBitmapDataBytes, angleBracket);
|
||||
result = GetImageProperty(blurHasher, item.ImageFileHolder, result, populateId, isIgnoreExtension, item.IsValidImageFormatExtension, isValidMetadataExtensions, id, _ASCIIEncoding, _Configuration.WriteBitmapDataBytes, angleBracket);
|
||||
json = JsonSerializer.Serialize(result, _WriteIndentedJsonSerializerOptions);
|
||||
if (populateId && Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: true, compareBeforeWrite: true))
|
||||
{
|
||||
@ -388,7 +417,7 @@ public class A_Property
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SavePropertyParallelForWork(string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
|
||||
private void SavePropertyParallelForWork(Shared.Models.Methods.IBlurHasher? blurHasher, string sourceDirectory, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item item)
|
||||
{
|
||||
Shared.Models.Property property;
|
||||
List<string> parseExceptions = new();
|
||||
@ -399,7 +428,7 @@ public class A_Property
|
||||
File.Move(item.ImageFileHolder.FullName, filteredSourceDirectoryFileExtensionLowered);
|
||||
if (item.FileSizeChanged is null || item.FileSizeChanged.Value || item.LastWriteTimeChanged is null || item.LastWriteTimeChanged.Value || item.Property is null)
|
||||
{
|
||||
property = GetPropertyOfPrivate(item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
|
||||
property = GetPropertyOfPrivate(blurHasher, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
|
||||
lock (sourceDirectoryChanges)
|
||||
sourceDirectoryChanges.Add(new Tuple<string, DateTime>(nameof(A_Property), DateTime.Now));
|
||||
lock (item)
|
||||
@ -407,10 +436,10 @@ public class A_Property
|
||||
}
|
||||
}
|
||||
|
||||
private void SavePropertyParallelWork(List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container container, List<Item> items, string message)
|
||||
private void SavePropertyParallelWork(int maxDegreeOfParallelism, Shared.Models.Methods.IBlurHasher? blurHasher, List<Exception> exceptions, List<Tuple<string, DateTime>> sourceDirectoryChanges, Container container, List<Item> items, string message)
|
||||
{
|
||||
List<Tuple<string, DateTime>> sourceDirectoryFileTuples = new();
|
||||
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _MaxDegreeOfParallelism };
|
||||
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) =>
|
||||
@ -420,7 +449,7 @@ public class A_Property
|
||||
long ticks = DateTime.Now.Ticks;
|
||||
DateTime dateTime = DateTime.Now;
|
||||
List<Tuple<string, DateTime>> collection;
|
||||
SavePropertyParallelForWork(container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
|
||||
SavePropertyParallelForWork(blurHasher, container.SourceDirectory, sourceDirectoryChanges, sourceDirectoryFileTuples, items[i]);
|
||||
if (i == 0 || sourceDirectoryChanges.Any())
|
||||
progressBar.Tick();
|
||||
lock (sourceDirectoryFileTuples)
|
||||
@ -449,6 +478,9 @@ public class A_Property
|
||||
singletonDescription: "Properties for each image",
|
||||
collectionDescription: string.Empty,
|
||||
converted: false));
|
||||
string directory = _AngleBracketCollection[0].Replace("<>", "()");
|
||||
if (!Directory.Exists(directory))
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
private void SetAngleBracketCollection(string sourceDirectory, bool anyNullOrNoIsUniqueFileName)
|
||||
@ -463,7 +495,7 @@ public class A_Property
|
||||
SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||
}
|
||||
|
||||
public void SavePropertyParallelWork(long ticks, int t, Container[] containers)
|
||||
public void SavePropertyParallelWork(long ticks, int t, Container[] containers, Shared.Models.Methods.IBlurHasher? blurHasher)
|
||||
{
|
||||
if (_Log is null)
|
||||
throw new NullReferenceException(nameof(_Log));
|
||||
@ -489,7 +521,7 @@ public class A_Property
|
||||
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(exceptions, sourceDirectoryChanges, container, container.Items, message);
|
||||
SavePropertyParallelWork(_MaxDegreeOfParallelism, blurHasher, exceptions, sourceDirectoryChanges, container, container.Items, message);
|
||||
foreach (Exception exception in exceptions)
|
||||
_Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, exception.Message, Environment.NewLine, exception.StackTrace), exception);
|
||||
if (exceptions.Count == container.Items.Count)
|
||||
@ -510,7 +542,7 @@ public class A_Property
|
||||
}
|
||||
}
|
||||
|
||||
public Shared.Models.Property GetProperty(Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
|
||||
public Shared.Models.Property GetProperty(Shared.Models.Methods.IBlurHasher? blurHasher, Item item, List<Tuple<string, DateTime>> sourceDirectoryFileTuples, List<string> parseExceptions)
|
||||
{
|
||||
Shared.Models.Property result;
|
||||
bool angleBracketCollectionAny = _AngleBracketCollection.Any();
|
||||
@ -522,7 +554,7 @@ public class A_Property
|
||||
}
|
||||
bool isValidMetadataExtensions = _Configuration.ValidMetadataExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
|
||||
bool isIgnoreExtension = item.IsValidImageFormatExtension && _Configuration.IgnoreExtensions.Contains(item.ImageFileHolder.ExtensionLowered);
|
||||
result = GetPropertyOfPrivate(item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
|
||||
result = GetPropertyOfPrivate(blurHasher, item, sourceDirectoryFileTuples, parseExceptions, isIgnoreExtension, isValidMetadataExtensions);
|
||||
if (!angleBracketCollectionAny)
|
||||
_AngleBracketCollection.Clear();
|
||||
return result;
|
||||
|
@ -40,10 +40,10 @@
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
9
Rename/.vscode/UserSecrets/secrets.json
vendored
Normal file
9
Rename/.vscode/UserSecrets/secrets.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"_Application": "Rename",
|
||||
"ComparePathsFile": "C:/Users/mikep/AppData/Local/PharesApps/Drag-Drop-Explorer/2023_21/638202586000194405.json",
|
||||
"Windows": {
|
||||
"Configuration": {
|
||||
"RootDirectory": "D:/1) Images A/Images-1e85c0ba"
|
||||
}
|
||||
}
|
||||
}
|
85
Rename/.vscode/tasks.json
vendored
85
Rename/.vscode/tasks.json
vendored
@ -1,41 +1,76 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"options": {
|
||||
"env": {
|
||||
"serverUserSecretsId": "6e026d2f-9edf-4c6c-a042-162758114e9a"
|
||||
}
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"label": "userSecretsInit",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/Rename.csproj",
|
||||
"init"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "userSecretsSet",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"user-secrets",
|
||||
"-p",
|
||||
"${workspaceFolder}/Rename.csproj",
|
||||
"set",
|
||||
"SaveDirectory",
|
||||
"D:/1) Images A/Images-1e85c0ba-Results/A2) People/1e85c0ba/([])"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "userSecretsMkLink",
|
||||
"command": "cmd",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"/c",
|
||||
"mklink",
|
||||
"/J",
|
||||
".vscode\\UserSecrets",
|
||||
"${userHome}\\AppData\\Roaming\\Microsoft\\UserSecrets\\$env:serverUserSecretsId"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "format",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"format",
|
||||
"--report",
|
||||
".vscode",
|
||||
"--verbosity",
|
||||
"detailed",
|
||||
"--severity",
|
||||
"warn"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Rename.csproj",
|
||||
"${workspaceFolder}/View-by-Distance-MKLink-Console.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Rename.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"--project",
|
||||
"${workspaceFolder}/Rename.csproj"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
@ -20,7 +20,8 @@ public class Program
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
|
||||
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true)
|
||||
.AddUserSecrets<Program>();
|
||||
IConfigurationRoot configurationRoot = configurationBuilder.Build();
|
||||
AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot);
|
||||
if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
|
||||
|
@ -3,9 +3,11 @@ using Phares.Shared;
|
||||
using Serilog;
|
||||
using ShellProgressBar;
|
||||
using System.Text.Json;
|
||||
using View_by_Distance.Property.Models;
|
||||
using View_by_Distance.Rename.Models;
|
||||
using View_by_Distance.Shared.Models;
|
||||
using View_by_Distance.Shared.Models.Methods;
|
||||
using View_by_Distance.Shared.Models.Stateless.Methods;
|
||||
|
||||
namespace View_by_Distance.Rename;
|
||||
|
||||
@ -15,7 +17,7 @@ public class Rename
|
||||
private readonly AppSettings _AppSettings;
|
||||
private readonly string _WorkingDirectory;
|
||||
private readonly IsEnvironment _IsEnvironment;
|
||||
private readonly Configuration _Configuration;
|
||||
private readonly Models.Configuration _Configuration;
|
||||
private readonly IConfigurationRoot _ConfigurationRoot;
|
||||
private readonly Property.Models.Configuration _PropertyConfiguration;
|
||||
|
||||
@ -34,7 +36,7 @@ public class Rename
|
||||
ILogger? log = Log.ForContext<Rename>();
|
||||
Dictionary<long, Dictionary<long, List<string>>> fileSizeToCollection = new();
|
||||
Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
|
||||
Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
|
||||
Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
|
||||
_PropertyConfiguration = propertyConfiguration;
|
||||
_Configuration = configuration;
|
||||
propertyConfiguration.Update();
|
||||
@ -63,6 +65,8 @@ public class Rename
|
||||
MoveMatches(matchNginxCollection[0]);
|
||||
else if (matchNginxCollection.All(l => l.Name.StartsWith("#")) || matchNginxCollection.All(l => l.Name.StartsWith(" #")) || matchNginxCollection.All(l => l.Name.StartsWith("=20")) || matchNginxCollection.All(l => l.Name.StartsWith("#20")))
|
||||
Rename2000(log, matchNginxCollection);
|
||||
else if (matchNginxCollection.All(l => l.Name.Length > 4) && matchNginxCollection.All(l => l.Name[0..3] is "198" or "199" or "200" or "201"))
|
||||
RenameByDateTaken(log, matchNginxCollection);
|
||||
else if (matchNginxCollection.Any())
|
||||
{
|
||||
List<string> lines = RenameFilesInDirectories(log, matchNginxCollection);
|
||||
@ -323,6 +327,8 @@ public class Rename
|
||||
continue;
|
||||
if (File.Exists(matchNginx.ConvertedPath))
|
||||
continue;
|
||||
if (!Directory.Exists(matchNginx.ConvertedPath))
|
||||
continue;
|
||||
files = Directory.GetFiles(matchNginx.ConvertedPath, "*", SearchOption.AllDirectories);
|
||||
if (files.All(l => l.EndsWith(".id")))
|
||||
{
|
||||
@ -425,8 +431,8 @@ public class Rename
|
||||
List<string> allFiles;
|
||||
ProgressBar progressBar;
|
||||
List<(FileHolder, string)> toDoCollection;
|
||||
List<(FileHolder, string)> verifiedToDoCollection;
|
||||
allFiles = GetAllFiles(matchNginxCollection);
|
||||
List<(FileHolder, string)> verifiedToDoCollection;
|
||||
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
@ -464,4 +470,88 @@ public class Rename
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
private void RenameByDateTakenB(MatchNginx[] matchNginxCollection, string aPropertySingletonDirectory, string[] jsonFiles)
|
||||
{
|
||||
string json;
|
||||
char directory;
|
||||
string[] files;
|
||||
string fileName;
|
||||
string extension;
|
||||
string[] matches;
|
||||
string checkFile;
|
||||
DateTime dateTime;
|
||||
string[] segments;
|
||||
string? checkFileName;
|
||||
string checkDirectory;
|
||||
string? subdirectory;
|
||||
Shared.Models.Property? property;
|
||||
foreach (MatchNginx matchNginx in matchNginxCollection)
|
||||
{
|
||||
if (File.Exists(matchNginx.ConvertedPath))
|
||||
continue;
|
||||
if (!Directory.Exists(matchNginx.ConvertedPath))
|
||||
continue;
|
||||
subdirectory = Path.GetDirectoryName(matchNginx.ConvertedPath);
|
||||
if (string.IsNullOrEmpty(subdirectory))
|
||||
continue;
|
||||
files = Directory.GetFiles(matchNginx.ConvertedPath, "*", SearchOption.AllDirectories);
|
||||
for (int i = 65; i < 91; i++)
|
||||
{
|
||||
checkDirectory = Path.Combine(subdirectory, nameof(Rename), ((char)i).ToString());
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
}
|
||||
foreach (string file in files)
|
||||
{
|
||||
fileName = Path.GetFileName(file);
|
||||
segments = fileName.Split('.');
|
||||
extension = Path.GetExtension(file);
|
||||
directory = IDirectory.GetDirectory(fileName);
|
||||
checkFileName = $"{segments.First()}{Path.GetExtension(Path.GetFileNameWithoutExtension(file))}.json";
|
||||
checkDirectory = Path.Combine(aPropertySingletonDirectory, _PropertyConfiguration.ResultAllInOne, directory.ToString());
|
||||
checkFile = Path.Combine(checkDirectory, checkFileName);
|
||||
matches = jsonFiles.Where(l => l == checkFile).ToArray();
|
||||
if (!matches.Any())
|
||||
{
|
||||
matches = jsonFiles.Where(l => l.EndsWith(checkFileName)).ToArray();
|
||||
if (!matches.Any())
|
||||
continue;
|
||||
}
|
||||
json = File.ReadAllText(matches.First());
|
||||
property = JsonSerializer.Deserialize<Shared.Models.Property>(json);
|
||||
if (property is null)
|
||||
continue;
|
||||
checkFileName = null;
|
||||
dateTime = property.DateTimeOriginal is not null ? property.DateTimeOriginal.Value : Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(property);
|
||||
for (int i = 65; i < 91; i++)
|
||||
{
|
||||
if (checkFileName is not null && !File.Exists(checkFileName))
|
||||
break;
|
||||
checkFileName = Path.Combine(subdirectory, nameof(Rename), ((char)i).ToString(), $"{dateTime.Ticks}{extension}");
|
||||
}
|
||||
if (checkFileName is null || File.Exists(checkFileName))
|
||||
continue;
|
||||
File.Move(file, checkFileName);
|
||||
}
|
||||
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(subdirectory);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenameByDateTaken(ILogger log, MatchNginx[] matchNginxCollection)
|
||||
{
|
||||
string aResultsFullGroupDirectory = Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(
|
||||
_PropertyConfiguration,
|
||||
nameof(A_Property),
|
||||
string.Empty,
|
||||
includeResizeGroup: false,
|
||||
includeModel: false,
|
||||
includePredictorModel: false);
|
||||
string aPropertySingletonDirectory = Path.GetFullPath(Path.Combine(aResultsFullGroupDirectory, "{}"));
|
||||
string[] jsonFiles = !Directory.Exists(aPropertySingletonDirectory) ? Array.Empty<string>() : Directory.GetFiles(aPropertySingletonDirectory, "*.json", SearchOption.AllDirectories);
|
||||
if (!jsonFiles.Any())
|
||||
log.Information($"No json file(s) found! Check directory <{aPropertySingletonDirectory}>");
|
||||
else
|
||||
RenameByDateTakenB(matchNginxCollection, aPropertySingletonDirectory, jsonFiles);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<UserSecretsId>6e026d2f-9edf-4c6c-a042-162758114e9a</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageId>Phares.View.by.Distance.Rename</PackageId>
|
||||
@ -38,7 +39,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
|
@ -1,14 +1,9 @@
|
||||
{
|
||||
"ComparePathsFile": "C:/Users/mikep/AppData/Local/PharesApps/Drag-Drop-Explorer/2023_13/638158781544395303.json",
|
||||
"CopyTo": "",
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Log4netProvider": "Debug"
|
||||
}
|
||||
},
|
||||
"MaxDegreeOfParallelism": 6,
|
||||
"MaxMinutesDelta": 2,
|
||||
"RenameUndo": false,
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Debug"
|
||||
},
|
||||
|
@ -68,7 +68,7 @@
|
||||
"ResultCollection": "[]",
|
||||
"ResultContent": "()",
|
||||
"ResultSingleton": "{}",
|
||||
"RootDirectory": "C:/Tmp/Phares/Compare/Images-1e85c0ba",
|
||||
"RootDirectory": "D:/Images",
|
||||
"WriteBitmapDataBytes": false,
|
||||
"IgnoreExtensions": [
|
||||
".gif",
|
||||
|
@ -56,9 +56,7 @@ public class C_Resize
|
||||
_PropertiesChangedForResize = propertiesChangedForResize;
|
||||
_ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime;
|
||||
_WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true };
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
|
||||
if (constructorInfo is null)
|
||||
throw new Exception();
|
||||
ConstructorInfo? constructorInfo = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null) ?? throw new Exception();
|
||||
_ConstructorInfo = constructorInfo;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.7.2" />
|
||||
<PackageReference Include="MetadataExtractor" Version="2.8.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
@ -43,5 +43,6 @@
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||
<ProjectReference Include="..\Property\Property.csproj" />
|
||||
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
14
Shared/Models/Methods/IBlurHasher.cs
Normal file
14
Shared/Models/Methods/IBlurHasher.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace View_by_Distance.Shared.Models.Methods;
|
||||
|
||||
public interface IBlurHasher
|
||||
{
|
||||
|
||||
string Encode(Image image);
|
||||
string Encode(Image image, int x, int y);
|
||||
string EncodeAndSave(Image image, string directory);
|
||||
string EncodeAndSave(Image image, int x, int y, string directory);
|
||||
string EncodeAndSave(Image image, int x, int y, int width, int height, string directory);
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ namespace View_by_Distance.Shared.Models.Properties;
|
||||
public interface IProperty
|
||||
{
|
||||
|
||||
public string? BlurHash { init; get; }
|
||||
public DateTime CreationTime { init; get; }
|
||||
public DateTime? DateTime { init; get; }
|
||||
public DateTime? DateTimeDigitized { init; get; }
|
||||
|
@ -6,6 +6,7 @@ namespace View_by_Distance.Shared.Models;
|
||||
public class Property : Properties.IProperty
|
||||
{
|
||||
|
||||
public string? BlurHash { init; get; }
|
||||
public DateTime CreationTime { init; get; }
|
||||
public DateTime? DateTime { init; get; }
|
||||
public DateTime? DateTimeDigitized { init; get; }
|
||||
@ -22,8 +23,9 @@ public class Property : Properties.IProperty
|
||||
public int? Width { init; get; }
|
||||
|
||||
[JsonConstructor]
|
||||
public Property(DateTime creationTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, long fileSize, DateTime? gpsDateStamp, int? height, int? id, DateTime lastWriteTime, string? make, string? model, string? orientation, int? width)
|
||||
public Property(string? blurHash, DateTime creationTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, long fileSize, DateTime? gpsDateStamp, int? height, int? id, DateTime lastWriteTime, string? make, string? model, string? orientation, int? width)
|
||||
{
|
||||
BlurHash = blurHash;
|
||||
DateTimeFromName = dateTimeFromName;
|
||||
CreationTime = creationTime;
|
||||
DateTime = dateTime;
|
||||
|
@ -27,25 +27,25 @@
|
||||
<DefineConstants>Linux</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
<ProjectReference Include="..\Property\Property.csproj" />
|
||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||
<ProjectReference Include="..\Resize\Resize.csproj" />
|
||||
<ProjectReference Include="..\Property-Compare\Property-Compare.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\Instance\appsettings.json">
|
||||
|
@ -46,6 +46,13 @@ public class UnitTestIsEnvironment
|
||||
_ConfigurationRoot = configurationRoot;
|
||||
}
|
||||
|
||||
private static void NonThrowTryCatch()
|
||||
{
|
||||
try
|
||||
{ throw new Exception(); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestMethodNull()
|
||||
{
|
||||
|
@ -64,6 +64,13 @@ public class UnitTestResize
|
||||
_PropertyConfiguration = propertyConfiguration;
|
||||
}
|
||||
|
||||
private static void NonThrowTryCatch()
|
||||
{
|
||||
try
|
||||
{ throw new Exception(); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestMethodNull()
|
||||
{
|
||||
@ -74,6 +81,7 @@ public class UnitTestResize
|
||||
Assert.IsFalse(_WorkingDirectory is null);
|
||||
Assert.IsFalse(_ConfigurationRoot is null);
|
||||
Assert.IsFalse(_PropertyConfiguration is null);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory)
|
||||
@ -121,17 +129,8 @@ public class UnitTestResize
|
||||
[TestMethod]
|
||||
public void TestMethodResize()
|
||||
{
|
||||
// string sourceFileName = "IMG_0067.jpg";
|
||||
// string sourceDirectoryName = "Mackenzie Prom 2017";
|
||||
// string sourceFileName = "Fall 2005 (113).jpg";
|
||||
// string sourceDirectoryName = "=2005.3 Fall";
|
||||
// string sourceFileName = "DSCN0534.jpg";
|
||||
// string sourceDirectoryName = "Logan Swimming Lessons 2013";
|
||||
// string sourceFileName = "DSC_4913.jpg";
|
||||
// string sourceDirectoryName = "Disneyland 2014";
|
||||
// string sourceFileName = "Logan Michael Sept 08 (193).jpg";
|
||||
// string sourceDirectoryName = "=2008.2 Summer Logan Michael";
|
||||
string sourceFileName = "Halloween 2006 (112).jpg";
|
||||
string sourceFileName = "640794601.jpg";
|
||||
// string sourceFileName = "input.jpg";
|
||||
string sourceDirectoryName = "Halloween 2006";
|
||||
Item item;
|
||||
bool reverse = false;
|
||||
@ -145,7 +144,6 @@ public class UnitTestResize
|
||||
int length = _PropertyConfiguration.RootDirectory.Length;
|
||||
string outputResolution = _Configuration.OutputResolutions[0];
|
||||
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
|
||||
string sourceDirectory = Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName);
|
||||
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
|
||||
_Logger.Information(_Configuration.ModelDirectory);
|
||||
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
|
||||
@ -160,16 +158,18 @@ public class UnitTestResize
|
||||
bool isUniqueFileName = false;
|
||||
bool? isNotUniqueAndNeedsReview = null;
|
||||
FileHolder sourceDirectoryFileHolder = new(".json");
|
||||
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
|
||||
FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName));
|
||||
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
|
||||
sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName);
|
||||
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory);
|
||||
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
|
||||
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
|
||||
resize.SetAngleBracketCollection(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, sourceDirectory);
|
||||
item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false);
|
||||
Assert.IsNotNull(item.ImageFileHolder);
|
||||
if (item.Property is null)
|
||||
{
|
||||
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
|
||||
Shared.Models.Methods.IBlurHasher? blurHasher = new BlurHash.Models.BlurHasher();
|
||||
property = propertyLogic.GetProperty(blurHasher, item, subFileTuples, parseExceptions);
|
||||
item.Update(property);
|
||||
}
|
||||
if (property is null || item.Property is null)
|
||||
@ -181,6 +181,7 @@ public class UnitTestResize
|
||||
outputResolutionToResize = resize.GetResizeKeyValuePairs(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, subFileTuples, parseExceptions, metadataCollection, item.Property, mappingFromItem);
|
||||
Assert.IsNotNull(mappingFromItem.ResizedFileHolder);
|
||||
resize.SaveResizedSubfile(_Configuration.PropertyConfiguration, outputResolution, cResultsFullGroupDirectory, subFileTuples, item, item.Property, mappingFromItem, outputResolutionToResize);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
}
|
@ -27,19 +27,20 @@
|
||||
<DefineConstants>Linux</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlurHash\BlurHash.csproj" />
|
||||
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
|
||||
<ProjectReference Include="..\Property\Property.csproj" />
|
||||
<ProjectReference Include="..\Metadata\Metadata.csproj" />
|
||||
|
@ -66,6 +66,13 @@ public class UnitTestFace
|
||||
_PropertyConfiguration = propertyConfiguration;
|
||||
}
|
||||
|
||||
private static void NonThrowTryCatch()
|
||||
{
|
||||
try
|
||||
{ throw new Exception(); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestConfiguration()
|
||||
{
|
||||
@ -73,6 +80,7 @@ public class UnitTestFace
|
||||
throw new Exception("Configuration has to match interface!");
|
||||
if (_Configuration.LocationFactor != Shared.Models.Stateless.ILocation.Factor)
|
||||
throw new Exception("Configuration has to match interface!");
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -85,6 +93,7 @@ public class UnitTestFace
|
||||
Assert.IsFalse(_WorkingDirectory is null);
|
||||
Assert.IsFalse(_ConfigurationRoot is null);
|
||||
Assert.IsFalse(_PropertyConfiguration is null);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
private A_Property GetPropertyLogic(bool reverse, string aResultsFullGroupDirectory)
|
||||
@ -156,6 +165,7 @@ public class UnitTestFace
|
||||
Assert.IsTrue(checkB > checkA);
|
||||
int checkC = (int)(_Configuration.RangeDistanceTolerance[1] * DistanceFactor);
|
||||
Assert.IsTrue(checkC == ToleranceAfterFactor);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
private (string, string) GetResultsFullGroupDirectories()
|
||||
@ -194,20 +204,8 @@ public class UnitTestFace
|
||||
[TestMethod]
|
||||
public void TestMethodFace()
|
||||
{
|
||||
// string sourceFileName = "IMG_0067.jpg";
|
||||
// string sourceDirectoryName = "Mackenzie Prom 2017";
|
||||
// string sourceFileName = "Fall 2005 (113).jpg";
|
||||
// string sourceDirectoryName = "=2005.3 Fall";
|
||||
// string sourceFileName = "DSCN0534.jpg";
|
||||
// string sourceDirectoryName = "Logan Swimming Lessons 2013";
|
||||
// string sourceFileName = "DSC_4913.jpg";
|
||||
// string sourceDirectoryName = "Disneyland 2014";
|
||||
// string sourceFileName = "Logan Michael Sept 08 (193).jpg";
|
||||
// string sourceDirectoryName = "=2008.2 Summer Logan Michael";
|
||||
// string sourceFileName = "Halloween 2006 (112).jpg";
|
||||
// string sourceDirectoryName = "Halloween 2006";
|
||||
string sourceFileName = "1384160978.jpg";
|
||||
string sourceDirectoryName = "zzz Portrait Innovations Files 2007";
|
||||
string sourceFileName = "640794601.jpg";
|
||||
string sourceDirectoryName = "Halloween 2006";
|
||||
Item item;
|
||||
bool reverse = false;
|
||||
FileHolder resizedFileHolder;
|
||||
@ -220,7 +218,6 @@ public class UnitTestFace
|
||||
int length = _PropertyConfiguration.RootDirectory.Length;
|
||||
string outputResolution = _Configuration.OutputResolutions[0];
|
||||
(string cResultsFullGroupDirectory, _, _) = GetResultsFullGroupDirectories(outputResolution);
|
||||
string sourceDirectory = Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName);
|
||||
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
|
||||
_Logger.Information(_Configuration.ModelDirectory);
|
||||
A_Property propertyLogic = GetPropertyLogic(reverse, aResultsFullGroupDirectory);
|
||||
@ -234,18 +231,19 @@ public class UnitTestFace
|
||||
_ = resize.ToString();
|
||||
bool isUniqueFileName = false;
|
||||
bool? isNotUniqueAndNeedsReview = null;
|
||||
bool anyNullOrNoIsUniqueFileName = true;
|
||||
FileHolder sourceDirectoryFileHolder = new(".json");
|
||||
string sourceDirectory = Path.GetFullPath(Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName));
|
||||
FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName));
|
||||
string relativePath = IPath.GetRelativePath(fileHolder.FullName, length);
|
||||
sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName);
|
||||
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, sourceDirectory, anyNullOrNoIsUniqueFileName);
|
||||
string propertyLogicSourceDirectory = Path.GetFullPath(Path.Combine(aPropertySingletonDirectory, sourceDirectoryName));
|
||||
propertyLogic.SetAngleBracketCollection(aResultsFullGroupDirectory, propertyLogicSourceDirectory);
|
||||
resize.SetAngleBracketCollection(_Configuration.PropertyConfiguration, cResultsFullGroupDirectory, sourceDirectory);
|
||||
item = new(sourceDirectoryFileHolder, relativePath, fileHolder, isNotUniqueAndNeedsReview, isUniqueFileName, isValidImageFormatExtension, property, false, false, false);
|
||||
Assert.IsNotNull(item.ImageFileHolder);
|
||||
if (item.Property is null)
|
||||
{
|
||||
property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
|
||||
Shared.Models.Methods.IBlurHasher? blurHasher = new BlurHash.Models.BlurHasher();
|
||||
property = propertyLogic.GetProperty(blurHasher, item, subFileTuples, parseExceptions);
|
||||
item.Update(property);
|
||||
}
|
||||
if (property is null || item.Property is null)
|
||||
@ -268,6 +266,7 @@ public class UnitTestFace
|
||||
List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]);
|
||||
Assert.IsTrue(faceDistanceLengths.Count == 2);
|
||||
Assert.IsNotNull(sourceFileName);
|
||||
NonThrowTryCatch();
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlurHash", "BlurHash\BlurHash.csproj", "{9689371E-F67C-4392-A636-C398D28C089B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Date-Group", "Date-Group\Date-Group.csproj", "{DFEDB5F9-AFFC-40A2-9FEC-9B84C83B63D9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delete-By-Distinct", "Delete-By-Distinct\Delete-By-Distinct.csproj", "{3F00BDD5-75F8-470C-ACED-1A26FDC8D7B3}"
|
||||
@ -13,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Distance", "Distance\Distan
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Explorer", "Drag-Drop-Explorer\Drag-Drop-Explorer.csproj", "{986B009B-2937-4624-AC9C-13806868DB8C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Move", "Drag-Drop-Move\Drag-Drop-Move.csproj", "{CF05EFAC-C212-4EE0-A644-3F728991AA54}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Search", "Drag-Drop-Search\Drag-Drop-Search.csproj", "{87EB76BC-32A9-4FD0-922A-BD7E9B6E7D8B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicate-Search", "Duplicate-Search\Duplicate-Search.csproj", "{48E87D9B-B802-467A-BDC7-E86F7FD01D5C}"
|
||||
@ -29,6 +33,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Map", "Map\Map.csproj", "{9
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata", "Metadata\Metadata.csproj", "{961D11A0-44C8-48CD-BEEE-A6E6903AE58F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Person", "Person\Person.csproj", "{C5003A39-334B-444B-9873-39B26E58D667}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhotoPrism", "PhotoPrism\PhotoPrism.csproj", "{DF4B0776-E0E5-4220-8721-8D1E491FF263}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrepareForOld", "PrepareForOld\PrepareForOld.csproj", "{F73F9468-0139-4B05-99CE-C6C0403D03E5}"
|
||||
@ -47,12 +55,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsWithFaceRecognitionDot
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "View-by-Distance.Shared", "shared\View-by-Distance.Shared.csproj", "{1D231660-33B4-4763-9C9F-C6ACC8BA600D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Person", "Person\Person.csproj", "{C5003A39-334B-444B-9873-39B26E58D667}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drag-Drop-Move", "Drag-Drop-Move\Drag-Drop-Move.csproj", "{CF05EFAC-C212-4EE0-A644-3F728991AA54}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -166,5 +168,9 @@ Global
|
||||
{CF05EFAC-C212-4EE0-A644-3F728991AA54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CF05EFAC-C212-4EE0-A644-3F728991AA54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CF05EFAC-C212-4EE0-A644-3F728991AA54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9689371E-F67C-4392-A636-C398D28C089B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9689371E-F67C-4392-A636-C398D28C089B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9689371E-F67C-4392-A636-C398D28C089B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9689371E-F67C-4392-A636-C398D28C089B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
Loading…
x
Reference in New Issue
Block a user