deterministicHashCode

This commit is contained in:
Mike Phares 2023-10-23 09:45:18 -07:00
parent 42d202e287
commit 05c27a891b
11 changed files with 240 additions and 63 deletions

View File

@ -4,6 +4,7 @@ using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Metadata.Models.Stateless.Methods; using View_by_Distance.Metadata.Models.Stateless.Methods;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties; using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Metadata.Models; namespace View_by_Distance.Metadata.Models;
@ -29,13 +30,11 @@ public class A_Metadata
_FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(aAConfiguration, bResultsFullGroupDirectory, [aAConfiguration.ResultSingleton]); _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(aAConfiguration, bResultsFullGroupDirectory, [aAConfiguration.ResultSingleton]);
} }
public ExifDirectory GetMetadataCollection(IMetadataConfiguration metadataConfiguration, string file, NameWithoutExtension nameWithoutExtension) public ExifDirectory GetMetadataCollection(IMetadataConfiguration metadataConfiguration, FilePath filePath, DeterministicHashCode deterministicHashCode)
{ {
ExifDirectory? results; ExifDirectory? results;
string fileName = Path.GetFileName(file); (_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_AAConfiguration.ResultAllInOneSubdirectoryLength, filePath.Name);
string fileExtensionLowered = Path.GetExtension(file).ToLower(); FileInfo fileInfo = new(Path.Combine(_FileGroups[_AAConfiguration.ResultSingleton][directoryIndex], $"{filePath.NameWithoutExtension}{filePath.ExtensionLowered}.json"));
(_, int directoryIndex) = Shared.Models.Stateless.Methods.IPath.GetDirectoryNameAndIndex(_AAConfiguration.ResultAllInOneSubdirectoryLength, fileName);
FileInfo fileInfo = new(Path.Combine(_FileGroups[_AAConfiguration.ResultSingleton][directoryIndex], $"{nameWithoutExtension.FileNameWithoutExtension}{fileExtensionLowered}.json"));
if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete")))
{ {
File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName);
@ -70,12 +69,12 @@ public class A_Metadata
{ {
System.Drawing.Size? size; System.Drawing.Size? size;
try try
{ size = Dimensions.GetDimensions(file); } { size = Dimensions.GetDimensions(filePath.FullName); }
catch (Exception) { size = null; } catch (Exception) { size = null; }
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(file); IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(filePath.FullName);
results = Exif.Covert(file, fileInfo, size, directories); results = Exif.Covert(filePath, deterministicHashCode, fileInfo, size, directories);
string json = JsonSerializer.Serialize(results, ExifDirectorySourceGenerationContext.Default.ExifDirectory); string json = JsonSerializer.Serialize(results, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null) && _ForceMetadataLastWriteTimeToCreationTime) if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null) && _ForceMetadataLastWriteTimeToCreationTime)
{ {
@ -86,15 +85,28 @@ public class A_Metadata
return results; return results;
} }
public static Action<string> GetResultCollection(IMetadataConfiguration metadataConfiguration, A_Metadata metadata, List<ExifDirectory> exifDirectories, Action tick) public static Action<string> GetResultCollection(IRename rename, IMetadataConfiguration metadataConfiguration, A_Metadata metadata, List<ExifDirectory> exifDirectories, Action tick)
{ {
return file => return file =>
{ {
tick.Invoke(); tick.Invoke();
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); FilePath filePath = Shared.Models.Stateless.Methods.IId.GetFilePath(metadataConfiguration, file);
NameWithoutExtension nameWithoutExtension = Shared.Models.Stateless.Methods.IId.GetNameWithoutExtension(metadataConfiguration, fileNameWithoutExtension); if (filePath.ExtensionLowered is not ".paddedId" and not ".lsv")
lock (exifDirectories) {
exifDirectories.Add(metadata.GetMetadataCollection(metadataConfiguration, file, nameWithoutExtension)); if (filePath.Id is null || (!filePath.IsIdFormat && !filePath.IsPaddedIdFormat))
{
string[]? ffmpegFiles = rename.ConvertAndGetFfmpegFiles(filePath);
filePath = ffmpegFiles is null || ffmpegFiles.Length < 0 ? filePath : IId.GetFilePath(filePath, ffmpegFiles[0]);
DeterministicHashCode deterministicHashCode = filePath.Id is not null ? deterministicHashCode = new(null, filePath.Id, null) : deterministicHashCode = rename.GetDeterministicHashCode(filePath);
if (ffmpegFiles is not null)
{
foreach (string ffmpegFile in ffmpegFiles)
File.Delete(ffmpegFile);
}
lock (exifDirectories)
exifDirectories.Add(metadata.GetMetadataCollection(metadataConfiguration, filePath, deterministicHashCode));
}
}
}; };
} }

View File

@ -322,7 +322,7 @@ internal abstract class Exif
return result; return result;
} }
internal static Shared.Models.ExifDirectory Covert(string file, FileInfo fileInfo, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories) internal static Shared.Models.ExifDirectory Covert(Shared.Models.FilePath filePath, Shared.Models.DeterministicHashCode deterministicHashCode, FileInfo fileInfo, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories)
{ {
Shared.Models.ExifDirectory results; Shared.Models.ExifDirectory results;
Shared.Models.AviDirectory aviDirectory = GetAviDirectory(directories); Shared.Models.AviDirectory aviDirectory = GetAviDirectory(directories);
@ -333,16 +333,17 @@ internal abstract class Exif
Shared.Models.ExifDirectoryBase exifDirectoryBase = GetExifDirectoryBase(directories); Shared.Models.ExifDirectoryBase exifDirectoryBase = GetExifDirectoryBase(directories);
Shared.Models.GifHeaderDirectory gifHeaderDirectory = GetGifHeaderDirectory(directories); Shared.Models.GifHeaderDirectory gifHeaderDirectory = GetGifHeaderDirectory(directories);
Shared.Models.PhotoshopDirectory photoshopDirectory = GetPhotoshopDirectory(directories); Shared.Models.PhotoshopDirectory photoshopDirectory = GetPhotoshopDirectory(directories);
Shared.Models.FileMetadataDirectory fileMetadataDirectory = GetFileMetadataDirectory(file, directories); Shared.Models.FileMetadataDirectory fileMetadataDirectory = GetFileMetadataDirectory(filePath.FullName, directories);
Shared.Models.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory = GetQuickTimeMovieHeaderDirectoryDirectory(directories); Shared.Models.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory = GetQuickTimeMovieHeaderDirectoryDirectory(directories);
Shared.Models.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory = GetQuickTimeTrackHeaderDirectoryDirectory(directories); Shared.Models.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory = GetQuickTimeTrackHeaderDirectoryDirectory(directories);
results = new(aviDirectory, results = new(aviDirectory,
exifDirectoryBase, exifDirectoryBase,
file, filePath.FullName,
fileMetadataDirectory, fileMetadataDirectory,
gifHeaderDirectory, gifHeaderDirectory,
gpsDirectory, gpsDirectory,
size?.Height, size?.Height,
deterministicHashCode.Id ?? filePath.Id,
fileInfo.FullName, fileInfo.FullName,
jpegDirectory, jpegDirectory,
photoshopDirectory, photoshopDirectory,

View File

@ -11,11 +11,6 @@ public interface IMetadata
Meters Meters
} }
Shared.Models.ExifDirectory TestStatic_Convert(string file, FileInfo fileInfo, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories) =>
Convert(file, fileInfo, size, directories);
static Shared.Models.ExifDirectory Convert(string file, FileInfo fileInfo, System.Drawing.Size? size, IReadOnlyList<MetadataExtractor.Directory> directories) =>
Exif.Covert(file, fileInfo, size, directories);
double? TestStatic_GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) => double? TestStatic_GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>
GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit); GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit);
static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) => static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) =>

View File

@ -1,6 +1,10 @@
using CliWrap;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShellProgressBar; using ShellProgressBar;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using View_by_Distance.Metadata.Models; using View_by_Distance.Metadata.Models;
using View_by_Distance.Rename.Models; using View_by_Distance.Rename.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
@ -8,7 +12,7 @@ using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Rename; namespace View_by_Distance.Rename;
public class Rename public class Rename : IRename
{ {
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
@ -94,28 +98,115 @@ public class Rename
return result; return result;
} }
string[]? IRename.ConvertAndGetFfmpegFiles(FilePath filePath)
{
string[]? results;
bool isIgnoreExtension;
bool isValidImageFormatExtension = _MetadataConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _MetadataConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered);
if (!isIgnoreExtension && isValidImageFormatExtension)
results = null;
else
{
CommandTask<CommandResult> commandTask = Cli.Wrap("ffmpeg.exe")
// .WithArguments(new[] { "-ss", "00:00:00", "-t", "00:00:00", "-i", files[i], "-qscale:v", "2", "-r", "0.01", $"{fileHolder.Name}-%4d.jpg" })
.WithArguments(new[] { "-i", filePath.FullName, "-vframes", "1", $"{filePath.Name}-%4d.jpg" })
.WithWorkingDirectory(filePath.DirectoryName)
.ExecuteAsync();
commandTask.Task.Wait();
results = Directory.GetFiles(filePath.DirectoryName, $"{filePath.Name}-*.jpg", SearchOption.TopDirectoryOnly);
if (results.Length == 0)
throw new Exception();
if (!filePath.Name.EndsWith("-0001.jpg"))
throw new Exception();
isValidImageFormatExtension = _MetadataConfiguration.ValidImageFormatExtensions.Contains(filePath.ExtensionLowered);
isIgnoreExtension = isValidImageFormatExtension && _MetadataConfiguration.IgnoreExtensions.Contains(filePath.ExtensionLowered);
if (isIgnoreExtension || !isValidImageFormatExtension)
throw new Exception();
if (filePath.DirectoryName is null)
throw new NullReferenceException(nameof(filePath.DirectoryName));
}
return results;
}
#pragma warning disable CA1416
DeterministicHashCode IRename.GetDeterministicHashCode(FilePath filePath)
{
DeterministicHashCode result;
int? id;
int? width;
int? height;
try
{
using Image image = Image.FromFile(filePath.FullName);
width = image.Width;
height = image.Height;
using Bitmap bitmap = new(image);
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
int length = bitmapData.Stride * bitmap.Height;
byte[] bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
id = IId.GetDeterministicHashCode(bytes);
}
catch (Exception)
{
id = null;
width = null;
height = null;
}
result = new(height, id, width);
return result;
}
#pragma warning restore CA1416
private void GetResultCollection(IRename rename, List<ExifDirectory> exifDirectories, IEnumerable<string> files, A_Metadata metadata)
{
string[]? ffmpegFiles;
DeterministicHashCode deterministicHashCode;
foreach (string file in files)
{
FilePath filePath = IId.GetFilePath(_MetadataConfiguration, file);
if (filePath.ExtensionLowered is ".paddedId" or ".lsv")
continue;
if (files.Contains($"{filePath.FullName}.paddedId"))
continue;
if (filePath.Id is not null && (filePath.IsIdFormat || filePath.IsPaddedIdFormat))
continue;
ffmpegFiles = rename.ConvertAndGetFfmpegFiles(filePath);
filePath = ffmpegFiles is null || ffmpegFiles.Length < 0 ? filePath : IId.GetFilePath(filePath, ffmpegFiles[0]);
if (filePath.Id is not null)
deterministicHashCode = new(null, filePath.Id, null);
else
deterministicHashCode = rename.GetDeterministicHashCode(filePath);
if (ffmpegFiles is not null)
{
foreach (string ffmpegFile in ffmpegFiles)
File.Delete(ffmpegFile);
}
exifDirectories.Add(metadata.GetMetadataCollection(_MetadataConfiguration, filePath, deterministicHashCode));
}
}
private List<string> RenameFilesInDirectories(ILogger? logger, long ticks, DirectoryInfo directoryInfo) private List<string> RenameFilesInDirectories(ILogger? logger, long ticks, DirectoryInfo directoryInfo)
{ {
List<string> old = []; List<string> old = [];
IRename rename = this;
List<ExifDirectory> exifDirectories = []; List<ExifDirectory> exifDirectories = [];
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks, directoryInfo); bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks, directoryInfo);
IEnumerable<string> files = Directory.EnumerateFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories); IEnumerable<string> files = Directory.EnumerateFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories);
A_Metadata metadata = new(_MetadataConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata); A_Metadata metadata = new(_MetadataConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata);
if (runToDoCollectionFirst) if (runToDoCollectionFirst)
{ GetResultCollection(rename, exifDirectories, files, metadata);
foreach (string file in files)
{
NameWithoutExtension nameWithoutExtension = IId.GetNameWithoutExtension(_MetadataConfiguration, file);
exifDirectories.Add(metadata.GetMetadataCollection(_MetadataConfiguration, file, nameWithoutExtension));
if (nameWithoutExtension.Id is null || (!nameWithoutExtension.IsIdFormat && !nameWithoutExtension.IsPaddedIdFormat))
;
}
}
else else
{ {
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism };
ProgressBar progressBar = new(123000, "EnumerateFiles load", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }); ProgressBar progressBar = new(123000, "EnumerateFiles load", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true });
files.AsParallel().ForAll(A_Metadata.GetResultCollection(_MetadataConfiguration, metadata, exifDirectories, () => progressBar.Tick())); files.AsParallel().ForAll(A_Metadata.GetResultCollection(rename, _MetadataConfiguration, metadata, exifDirectories, () => progressBar.Tick()));
if (progressBar.CurrentTick != exifDirectories.Count) if (progressBar.CurrentTick != exifDirectories.Count)
throw new NotSupportedException(); throw new NotSupportedException();
} }

View File

@ -0,0 +1,23 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record DeterministicHashCode(int? Height,
int? Id,
int? Width)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, DeterministicHashCodeSourceGenerationContext.Default.DeterministicHashCode);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(DeterministicHashCode))]
public partial class DeterministicHashCodeSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -10,6 +10,7 @@ public record ExifDirectory(AviDirectory AviDirectory,
GifHeaderDirectory GifHeaderDirectory, GifHeaderDirectory GifHeaderDirectory,
GpsDirectory GpsDirectory, GpsDirectory GpsDirectory,
int? Height, int? Height,
int? Id,
string JsonFile, string JsonFile,
JpegDirectory JpegDirectory, JpegDirectory JpegDirectory,
PhotoshopDirectory PhotoshopDirectory, PhotoshopDirectory PhotoshopDirectory,

28
Shared/Models/FilePath.cs Normal file
View File

@ -0,0 +1,28 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record FilePath(string DirectoryName,
string ExtensionLowered,
string FullName,
int? Id,
bool IsIdFormat,
bool IsPaddedIdFormat,
string Name,
string NameWithoutExtension)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, FilePathSourceGenerationContext.Default.FilePath);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(FilePath))]
public partial class FilePathSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -1,24 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record NameWithoutExtension(string FileNameWithoutExtension,
int? Id,
bool IsIdFormat,
bool IsPaddedIdFormat)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, NameWithoutExtensionSourceGenerationContext.Default.NameWithoutExtension);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(NameWithoutExtension))]
public partial class NameWithoutExtensionSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -20,15 +20,27 @@ internal abstract class Id
return result; return result;
} }
internal static NameWithoutExtension GetNameWithoutExtension(IMetadataConfiguration configuration, string file) internal static FilePath GetFilePath(FilePath filePath, string file)
{ {
NameWithoutExtension result; FilePath result;
string fileName = Path.GetFileName(file);
string fileExtensionLowered = Path.GetExtension(file).ToLower();
result = new(filePath.DirectoryName, fileExtensionLowered, file, filePath.Id, filePath.IsIdFormat, filePath.IsPaddedIdFormat, fileName, filePath.NameWithoutExtension);
return result;
}
internal static FilePath GetFilePath(IMetadataConfiguration configuration, string file)
{
FilePath result;
int? id; int? id;
short? multiplier; short? multiplier;
char negativeMarker; char negativeMarker;
int absoluteValueOfId; int absoluteValueOfId;
string fileName = Path.GetFileName(file);
string fileExtensionLowered = Path.GetExtension(file).ToLower();
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
short sortOrderOnlyLengthIndex = IId.GetSortOrderOnlyLengthIndex(configuration.Offset); short sortOrderOnlyLengthIndex = IId.GetSortOrderOnlyLengthIndex(configuration.Offset);
string fileDirectoryName = Path.GetDirectoryName(file) ?? throw new NullReferenceException();
bool nameWithoutExtensionIsIdFormat = IId.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension); bool nameWithoutExtensionIsIdFormat = IId.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
bool nameWithoutExtensionIsPaddedIdFormat = IId.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex); bool nameWithoutExtensionIsPaddedIdFormat = IId.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat) if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat)
@ -58,7 +70,26 @@ internal abstract class Id
id = null; id = null;
} }
} }
result = new(fileNameWithoutExtension, id, nameWithoutExtensionIsIdFormat, nameWithoutExtensionIsPaddedIdFormat); result = new(fileDirectoryName, fileExtensionLowered, file, id, nameWithoutExtensionIsIdFormat, nameWithoutExtensionIsPaddedIdFormat, fileName, fileNameWithoutExtension);
return result;
}
internal static int GetDeterministicHashCode(byte[] value)
{
int result;
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < value.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ value[i];
if (i == value.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ value[i + 1];
}
result = hash1 + (hash2 * 1566083941);
}
return result; return result;
} }

View File

@ -33,9 +33,19 @@ public interface IId
static short GetSortOrderOnlyLengthIndex(int offset) => static short GetSortOrderOnlyLengthIndex(int offset) =>
(short)(offset.ToString().Length + 3); (short)(offset.ToString().Length + 3);
NameWithoutExtension TestStatic_GetNameWithoutExtension(IMetadataConfiguration configuration, string file) => FilePath TestStatic_GetFilePath(FilePath filePath, string file) =>
GetNameWithoutExtension(configuration, file); GetFilePath(filePath, file);
static NameWithoutExtension GetNameWithoutExtension(IMetadataConfiguration configuration, string file) => static FilePath GetFilePath(FilePath filePath, string file) =>
Id.GetNameWithoutExtension(configuration, file); Id.GetFilePath(filePath, file);
FilePath TestStatic_GetFilePath(IMetadataConfiguration configuration, string file) =>
GetFilePath(configuration, file);
static FilePath GetFilePath(IMetadataConfiguration configuration, string file) =>
Id.GetFilePath(configuration, file);
int TestStatic_GetDeterministicHashCode(byte[] value) =>
GetDeterministicHashCode(value);
static int GetDeterministicHashCode(byte[] value) =>
Id.GetDeterministicHashCode(value);
} }

View File

@ -0,0 +1,9 @@
namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IRename
{
string[]? ConvertAndGetFfmpegFiles(FilePath filePath);
DeterministicHashCode GetDeterministicHashCode(FilePath filePath);
}