Exif Helper
This commit is contained in:
parent
19326df4c6
commit
80ca8f98eb
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@ -11,6 +11,7 @@
|
|||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
|
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
|
||||||
"args": [
|
"args": [
|
||||||
|
"D:/5-Other-Small/Proxmox/exiftool/286628400329.jpg.jpg",
|
||||||
"s",
|
"s",
|
||||||
"X",
|
"X",
|
||||||
"L:/DevOps/Mesa_FI/File-Folder-Helper/.vscode/helper/tfs",
|
"L:/DevOps/Mesa_FI/File-Folder-Helper/.vscode/helper/tfs",
|
||||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -15,6 +15,7 @@
|
|||||||
"CHIL",
|
"CHIL",
|
||||||
"DEAT",
|
"DEAT",
|
||||||
"endianness",
|
"endianness",
|
||||||
|
"Exif",
|
||||||
"FAMC",
|
"FAMC",
|
||||||
"FAMS",
|
"FAMS",
|
||||||
"GIVN",
|
"GIVN",
|
||||||
@ -29,6 +30,7 @@
|
|||||||
"NSFX",
|
"NSFX",
|
||||||
"OBJE",
|
"OBJE",
|
||||||
"onenote",
|
"onenote",
|
||||||
|
"Permyriad",
|
||||||
"pged",
|
"pged",
|
||||||
"Phares",
|
"Phares",
|
||||||
"Reparse",
|
"Reparse",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
|
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
|
||||||
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
|
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
|
||||||
|
<PackageReference Include="MetadataExtractor" Version="2.8.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="19.225.1" />
|
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="19.225.1" />
|
||||||
|
126
Helpers/Exif/Dimensions.cs
Normal file
126
Helpers/Exif/Dimensions.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Helpers.Exif;
|
||||||
|
|
||||||
|
internal static class Dimensions
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma warning disable IDE0230
|
||||||
|
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||||
|
{
|
||||||
|
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||||
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
||||||
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
||||||
|
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
||||||
|
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||||
|
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||||
|
};
|
||||||
|
#pragma warning restore IDE0230
|
||||||
|
|
||||||
|
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < thatBytes.Length; i += 1)
|
||||||
|
{
|
||||||
|
if (thisBytes[i] == thatBytes[i])
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static short ReadLittleEndianInt16(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[sizeof(short)];
|
||||||
|
for (int i = 0; i < sizeof(short); i += 1)
|
||||||
|
bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
|
||||||
|
return BitConverter.ToInt16(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ReadLittleEndianInt32(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[sizeof(int)];
|
||||||
|
for (int i = 0; i < sizeof(int); i += 1)
|
||||||
|
bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
|
||||||
|
return BitConverter.ToInt32(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeBitmap(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadBytes(16);
|
||||||
|
int width = binaryReader.ReadInt32();
|
||||||
|
int height = binaryReader.ReadInt32();
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeGif(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
int width = binaryReader.ReadInt16();
|
||||||
|
int height = binaryReader.ReadInt16();
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodePng(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadBytes(8);
|
||||||
|
int width = ReadLittleEndianInt32(binaryReader);
|
||||||
|
int height = ReadLittleEndianInt32(binaryReader);
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeJfif(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
while (binaryReader.ReadByte() == 0xff)
|
||||||
|
{
|
||||||
|
byte marker = binaryReader.ReadByte();
|
||||||
|
short chunkLength = ReadLittleEndianInt16(binaryReader);
|
||||||
|
if (marker == 0xc0)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadByte();
|
||||||
|
int height = ReadLittleEndianInt16(binaryReader);
|
||||||
|
int width = ReadLittleEndianInt16(binaryReader);
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
if (chunkLength >= 0)
|
||||||
|
_ = binaryReader.ReadBytes(chunkLength - 2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ushort uChunkLength = (ushort)chunkLength;
|
||||||
|
_ = binaryReader.ReadBytes(uChunkLength - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeWebP(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadUInt32(); // Size
|
||||||
|
_ = binaryReader.ReadBytes(15); // WEBP, VP8 + more
|
||||||
|
_ = binaryReader.ReadBytes(3); // SYNC
|
||||||
|
int width = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits width
|
||||||
|
int height = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits height
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Size? GetDimensions(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
|
||||||
|
byte[] magicBytes = new byte[maxMagicBytesLength];
|
||||||
|
for (int i = 0; i < maxMagicBytesLength; i += 1)
|
||||||
|
{
|
||||||
|
magicBytes[i] = binaryReader.ReadByte();
|
||||||
|
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
||||||
|
{
|
||||||
|
if (StartsWith(magicBytes, kvPair.Key))
|
||||||
|
return kvPair.Value(binaryReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Size? GetDimensions(string path)
|
||||||
|
{
|
||||||
|
using BinaryReader binaryReader = new(File.OpenRead(path));
|
||||||
|
return GetDimensions(binaryReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
534
Helpers/Exif/Exif.cs
Normal file
534
Helpers/Exif/Exif.cs
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
using MetadataExtractor;
|
||||||
|
using MetadataExtractor.Formats.Exif;
|
||||||
|
using MetadataExtractor.Formats.Exif.Makernotes;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Helpers.Exif;
|
||||||
|
|
||||||
|
internal abstract class Exif
|
||||||
|
{
|
||||||
|
|
||||||
|
private static DateTime? GetDateTime(string? value)
|
||||||
|
{
|
||||||
|
DateTime? result;
|
||||||
|
string dateTimeFormat = "yyyy:MM:dd HH:mm:ss";
|
||||||
|
string alternateFormat = "ddd MMM dd HH:mm:ss yyyy";
|
||||||
|
if (value is not null && DateTime.TryParse(value, out DateTime dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == dateTimeFormat.Length && DateTime.TryParseExact(value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else if (value is not null && value.Length == alternateFormat.Length && DateTime.TryParseExact(value, alternateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||||
|
result = dateTime;
|
||||||
|
else
|
||||||
|
result = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.AviDirectory[] GetAviDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.AviDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.Avi.AviDirectory> aviDirectories = directories.OfType<MetadataExtractor.Formats.Avi.AviDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.Avi.AviDirectory aviDirectory in aviDirectories)
|
||||||
|
{
|
||||||
|
if (aviDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? dateTimeOriginal;
|
||||||
|
string? duration = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagDuration);
|
||||||
|
string? height = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagHeight);
|
||||||
|
string? width = aviDirectory.GetDescription(MetadataExtractor.Formats.Avi.AviDirectory.TagWidth);
|
||||||
|
if (aviDirectory.TryGetDateTime(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal, out DateTime checkDateTime))
|
||||||
|
dateTimeOriginal = checkDateTime;
|
||||||
|
else
|
||||||
|
dateTimeOriginal = GetDateTime(aviDirectory.GetString(MetadataExtractor.Formats.Avi.AviDirectory.TagDateTimeOriginal));
|
||||||
|
if (dateTimeOriginal is null && duration is null && height is null && width is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(dateTimeOriginal, duration, height, width));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.ExifDirectoryBase[] GetExifBaseDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.ExifDirectoryBase> results = [];
|
||||||
|
IEnumerable<ExifDirectoryBase> exifBaseDirectories = directories.OfType<ExifDirectoryBase>();
|
||||||
|
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
|
||||||
|
{
|
||||||
|
if (exifDirectoryBase.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? dateTime;
|
||||||
|
DateTime checkDateTime;
|
||||||
|
DateTime? dateTimeOriginal;
|
||||||
|
DateTime? dateTimeDigitized;
|
||||||
|
string? aperture = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagAperture);
|
||||||
|
string? applicationNotes = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagApplicationNotes);
|
||||||
|
string? artist = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagArtist);
|
||||||
|
string? bitsPerSample = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBitsPerSample);
|
||||||
|
string? bodySerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagBodySerialNumber);
|
||||||
|
string? cameraOwnerName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCameraOwnerName);
|
||||||
|
string? compressedAverageBitsPerPixel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompressedAverageBitsPerPixel);
|
||||||
|
string? compression = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCompression);
|
||||||
|
string? copyright = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagCopyright);
|
||||||
|
string? documentName = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagDocumentName);
|
||||||
|
string? exifVersion = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExifVersion);
|
||||||
|
string? exposureTime = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagExposureTime);
|
||||||
|
string? fileSource = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagFileSource);
|
||||||
|
string? imageDescription = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageDescription);
|
||||||
|
string? imageHeight = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageHeight);
|
||||||
|
string? imageNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageNumber);
|
||||||
|
string? imageUniqueId = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageUniqueId);
|
||||||
|
string? imageWidth = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageWidth);
|
||||||
|
string? isoSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagIsoSpeed);
|
||||||
|
string? lensMake = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensMake);
|
||||||
|
string? lensModel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensModel);
|
||||||
|
string? lensSerialNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensSerialNumber);
|
||||||
|
string? make = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMake);
|
||||||
|
string? makerNote = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagMakernote);
|
||||||
|
string? model = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagModel);
|
||||||
|
string? orientation = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagOrientation);
|
||||||
|
int? orientationValue = orientation is null ? null : exifDirectoryBase.GetInt32(ExifDirectoryBase.TagOrientation);
|
||||||
|
string? rating = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRating);
|
||||||
|
string? ratingPercent = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagRatingPercent);
|
||||||
|
string? securityClassification = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSecurityClassification);
|
||||||
|
string? shutterSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagShutterSpeed);
|
||||||
|
string? software = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagSoftware);
|
||||||
|
string? timeZone = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZone);
|
||||||
|
string? timeZoneDigitized = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneDigitized);
|
||||||
|
string? timeZoneOriginal = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagTimeZoneOriginal);
|
||||||
|
string? userComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagUserComment);
|
||||||
|
string? winAuthor = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinAuthor);
|
||||||
|
string? winComment = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinComment);
|
||||||
|
string? winKeywords = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinKeywords);
|
||||||
|
string? winSubject = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinSubject);
|
||||||
|
string? winTitle = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagWinTitle);
|
||||||
|
string? xResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagXResolution);
|
||||||
|
string? yResolution = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagYResolution);
|
||||||
|
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out checkDateTime))
|
||||||
|
dateTime = checkDateTime;
|
||||||
|
else
|
||||||
|
dateTime = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTime));
|
||||||
|
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out checkDateTime))
|
||||||
|
dateTimeOriginal = checkDateTime;
|
||||||
|
else
|
||||||
|
dateTimeOriginal = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeOriginal));
|
||||||
|
if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out checkDateTime))
|
||||||
|
dateTimeDigitized = checkDateTime;
|
||||||
|
else
|
||||||
|
dateTimeDigitized = GetDateTime(exifDirectoryBase.GetString(ExifDirectoryBase.TagDateTimeDigitized));
|
||||||
|
if (userComment is not null && userComment.Length > 255)
|
||||||
|
userComment = "...";
|
||||||
|
if (aperture is null
|
||||||
|
&& applicationNotes is null
|
||||||
|
&& artist is null
|
||||||
|
&& bitsPerSample is null
|
||||||
|
&& bodySerialNumber is null
|
||||||
|
&& cameraOwnerName is null
|
||||||
|
&& compressedAverageBitsPerPixel is null
|
||||||
|
&& compression is null
|
||||||
|
&& copyright is null
|
||||||
|
&& dateTime is null
|
||||||
|
&& dateTimeDigitized is null
|
||||||
|
&& dateTimeOriginal is null
|
||||||
|
&& documentName is null
|
||||||
|
&& exifVersion is null
|
||||||
|
&& exposureTime is null
|
||||||
|
&& fileSource is null
|
||||||
|
&& imageDescription is null
|
||||||
|
&& imageHeight is null
|
||||||
|
&& imageNumber is null
|
||||||
|
&& imageUniqueId is null
|
||||||
|
&& imageWidth is null
|
||||||
|
&& isoSpeed is null
|
||||||
|
&& lensMake is null
|
||||||
|
&& lensModel is null
|
||||||
|
&& lensSerialNumber is null
|
||||||
|
&& make is null
|
||||||
|
&& makerNote is null
|
||||||
|
&& model is null
|
||||||
|
&& orientation is null
|
||||||
|
&& orientationValue is null
|
||||||
|
&& rating is null
|
||||||
|
&& ratingPercent is null
|
||||||
|
&& securityClassification is null
|
||||||
|
&& shutterSpeed is null
|
||||||
|
&& software is null
|
||||||
|
&& timeZone is null
|
||||||
|
&& timeZoneDigitized is null
|
||||||
|
&& timeZoneOriginal is null
|
||||||
|
&& userComment is null
|
||||||
|
&& winAuthor is null
|
||||||
|
&& winComment is null
|
||||||
|
&& winKeywords is null
|
||||||
|
&& winSubject is null
|
||||||
|
&& winTitle is null
|
||||||
|
&& xResolution is not null
|
||||||
|
&& yResolution is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(aperture,
|
||||||
|
applicationNotes,
|
||||||
|
artist,
|
||||||
|
bitsPerSample,
|
||||||
|
bodySerialNumber,
|
||||||
|
cameraOwnerName,
|
||||||
|
compressedAverageBitsPerPixel,
|
||||||
|
compression,
|
||||||
|
copyright,
|
||||||
|
dateTime,
|
||||||
|
dateTimeDigitized,
|
||||||
|
dateTimeOriginal,
|
||||||
|
documentName,
|
||||||
|
exifVersion,
|
||||||
|
exposureTime,
|
||||||
|
fileSource,
|
||||||
|
imageDescription,
|
||||||
|
imageHeight,
|
||||||
|
imageNumber,
|
||||||
|
imageUniqueId,
|
||||||
|
imageWidth,
|
||||||
|
isoSpeed,
|
||||||
|
lensMake,
|
||||||
|
lensModel,
|
||||||
|
lensSerialNumber,
|
||||||
|
make,
|
||||||
|
makerNote,
|
||||||
|
model,
|
||||||
|
orientation,
|
||||||
|
orientationValue,
|
||||||
|
rating,
|
||||||
|
ratingPercent,
|
||||||
|
securityClassification,
|
||||||
|
shutterSpeed,
|
||||||
|
software,
|
||||||
|
timeZone,
|
||||||
|
timeZoneDigitized,
|
||||||
|
timeZoneOriginal,
|
||||||
|
userComment,
|
||||||
|
winAuthor,
|
||||||
|
winComment,
|
||||||
|
winKeywords,
|
||||||
|
winSubject,
|
||||||
|
winTitle,
|
||||||
|
xResolution,
|
||||||
|
yResolution));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.FileMetadataDirectory[] GetFileMetadataDirectories(string file, IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.FileMetadataDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory> fileMetadataDirectories = directories.OfType<MetadataExtractor.Formats.FileSystem.FileMetadataDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.FileSystem.FileMetadataDirectory fileMetadataDirectory in fileMetadataDirectories)
|
||||||
|
{
|
||||||
|
if (fileMetadataDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? fileModifiedDate;
|
||||||
|
string? fileName = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileName);
|
||||||
|
string? fileSize = fileMetadataDirectory.GetDescription(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileSize);
|
||||||
|
if (fileMetadataDirectory.TryGetDateTime(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate, out DateTime checkDateTime))
|
||||||
|
fileModifiedDate = checkDateTime;
|
||||||
|
else
|
||||||
|
fileModifiedDate = GetDateTime(fileMetadataDirectory.GetString(MetadataExtractor.Formats.FileSystem.FileMetadataDirectory.TagFileModifiedDate));
|
||||||
|
if (fileName is null || !file.EndsWith(fileName))
|
||||||
|
throw new NotSupportedException($"!{file}.EndsWith({fileName})");
|
||||||
|
if (fileModifiedDate is null && fileName is null && fileSize is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(fileModifiedDate, fileName, fileSize));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.GifHeaderDirectory[] GetGifHeaderDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.GifHeaderDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.Gif.GifHeaderDirectory> gifHeaderDirectories = directories.OfType<MetadataExtractor.Formats.Gif.GifHeaderDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.Gif.GifHeaderDirectory gifHeaderDirectory in gifHeaderDirectories)
|
||||||
|
{
|
||||||
|
if (gifHeaderDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? imageHeight = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageHeight);
|
||||||
|
string? imageWidth = gifHeaderDirectory.GetDescription(MetadataExtractor.Formats.Gif.GifHeaderDirectory.TagImageWidth);
|
||||||
|
if (imageHeight is null && imageWidth is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(imageHeight, imageWidth));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.GpsDirectory[] GetGpsDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.GpsDirectory> results = [];
|
||||||
|
IEnumerable<GpsDirectory> gpsDirectories = directories.OfType<GpsDirectory>();
|
||||||
|
foreach (GpsDirectory gpsDirectory in gpsDirectories)
|
||||||
|
{
|
||||||
|
if (gpsDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? timeStamp;
|
||||||
|
string? altitude = gpsDirectory.GetDescription(GpsDirectory.TagAltitude);
|
||||||
|
string? latitude = gpsDirectory.GetDescription(GpsDirectory.TagLatitude);
|
||||||
|
string? latitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLatitudeRef);
|
||||||
|
string? longitude = gpsDirectory.GetDescription(GpsDirectory.TagLongitude);
|
||||||
|
string? longitudeRef = gpsDirectory.GetDescription(GpsDirectory.TagLongitudeRef);
|
||||||
|
if (gpsDirectory.TryGetDateTime(GpsDirectory.TagTimeStamp, out DateTime checkDateTime))
|
||||||
|
timeStamp = checkDateTime;
|
||||||
|
else
|
||||||
|
timeStamp = GetDateTime(gpsDirectory.GetString(GpsDirectory.TagTimeStamp));
|
||||||
|
if (altitude is null && latitude is null && latitudeRef is null && longitude is null && longitudeRef is null && timeStamp is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(altitude,
|
||||||
|
latitude,
|
||||||
|
latitudeRef,
|
||||||
|
longitude,
|
||||||
|
longitudeRef,
|
||||||
|
timeStamp));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.JpegDirectory[] GetJpegDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.JpegDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.Jpeg.JpegDirectory> jpegDirectories = directories.OfType<MetadataExtractor.Formats.Jpeg.JpegDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.Jpeg.JpegDirectory jpegDirectory in jpegDirectories)
|
||||||
|
{
|
||||||
|
if (jpegDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? imageHeight = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageHeight);
|
||||||
|
string? imageWidth = jpegDirectory.GetDescription(MetadataExtractor.Formats.Jpeg.JpegDirectory.TagImageWidth);
|
||||||
|
if (imageHeight is null && imageWidth is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(imageHeight, imageWidth));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.MakernoteDirectory[] GetMakernoteDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.MakernoteDirectory> results = [];
|
||||||
|
IEnumerable<AppleMakernoteDirectory> appleMakernoteDirectories = directories.OfType<AppleMakernoteDirectory>();
|
||||||
|
foreach (AppleMakernoteDirectory appleMakernoteDirectory in appleMakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (appleMakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = null;
|
||||||
|
string? firmwareVersion = null;
|
||||||
|
string? qualityAndFileFormat = null;
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<CanonMakernoteDirectory> canonMakernoteDirectories = directories.OfType<CanonMakernoteDirectory>();
|
||||||
|
foreach (CanonMakernoteDirectory canonMakernoteDirectory in canonMakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (canonMakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagModelId);
|
||||||
|
string? firmwareVersion = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.TagCanonFirmwareVersion);
|
||||||
|
string? qualityAndFileFormat = canonMakernoteDirectory.GetDescription(CanonMakernoteDirectory.CameraSettings.TagQuality);
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<NikonType2MakernoteDirectory> nikonType2MakernoteDirectories = directories.OfType<NikonType2MakernoteDirectory>();
|
||||||
|
foreach (NikonType2MakernoteDirectory nikonType2MakernoteDirectory in nikonType2MakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (nikonType2MakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagCameraSerialNumber);
|
||||||
|
string? firmwareVersion = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagFirmwareVersion);
|
||||||
|
string? qualityAndFileFormat = nikonType2MakernoteDirectory.GetDescription(NikonType2MakernoteDirectory.TagQualityAndFileFormat);
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<OlympusMakernoteDirectory> olympusMakernoteDirectories = directories.OfType<OlympusMakernoteDirectory>();
|
||||||
|
foreach (OlympusMakernoteDirectory olympusMakernoteDirectory in olympusMakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (olympusMakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagSerialNumber1);
|
||||||
|
string? firmwareVersion = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagBodyFirmwareVersion);
|
||||||
|
string? qualityAndFileFormat = olympusMakernoteDirectory.GetDescription(OlympusMakernoteDirectory.TagJpegQuality);
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<PanasonicMakernoteDirectory> panasonicMakernoteDirectories = directories.OfType<PanasonicMakernoteDirectory>();
|
||||||
|
foreach (PanasonicMakernoteDirectory panasonicMakernoteDirectory in panasonicMakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (panasonicMakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagInternalSerialNumber);
|
||||||
|
string? firmwareVersion = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagFirmwareVersion);
|
||||||
|
string? qualityAndFileFormat = panasonicMakernoteDirectory.GetDescription(PanasonicMakernoteDirectory.TagQualityMode);
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<SamsungType2MakernoteDirectory> samsungType2MakernoteDirectories = directories.OfType<SamsungType2MakernoteDirectory>();
|
||||||
|
foreach (SamsungType2MakernoteDirectory samsungType2MakernoteDirectory in samsungType2MakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (samsungType2MakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagSerialNumber);
|
||||||
|
string? firmwareVersion = samsungType2MakernoteDirectory.GetDescription(SamsungType2MakernoteDirectory.TagFirmwareName);
|
||||||
|
string? qualityAndFileFormat = null;
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
IEnumerable<SonyType6MakernoteDirectory> sonyType6MakernoteDirectories = directories.OfType<SonyType6MakernoteDirectory>();
|
||||||
|
foreach (SonyType6MakernoteDirectory sonyType6MakernoteDirectory in sonyType6MakernoteDirectories)
|
||||||
|
{
|
||||||
|
if (sonyType6MakernoteDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? cameraSerialNumber = null;
|
||||||
|
string? firmwareVersion = null;
|
||||||
|
string? qualityAndFileFormat = null;
|
||||||
|
if (cameraSerialNumber is null && firmwareVersion is null && qualityAndFileFormat is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(cameraSerialNumber, firmwareVersion, qualityAndFileFormat));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.PhotoshopDirectory[] GetPhotoshopDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.PhotoshopDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory> photoshopDirectories = directories.OfType<MetadataExtractor.Formats.Photoshop.PhotoshopDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.Photoshop.PhotoshopDirectory photoshopDirectory in photoshopDirectories)
|
||||||
|
{
|
||||||
|
if (photoshopDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? jpegQuality = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagJpegQuality);
|
||||||
|
string? url = photoshopDirectory.GetDescription(MetadataExtractor.Formats.Photoshop.PhotoshopDirectory.TagUrl);
|
||||||
|
if (jpegQuality is null && url is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(jpegQuality, url));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.PngDirectory[] GetPngDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.PngDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.Png.PngDirectory> pngDirectories = directories.OfType<MetadataExtractor.Formats.Png.PngDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.Png.PngDirectory pngDirectory in pngDirectories)
|
||||||
|
{
|
||||||
|
if (pngDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? imageHeight = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageHeight);
|
||||||
|
string? imageWidth = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagImageWidth);
|
||||||
|
string? textualData = pngDirectory.GetDescription(MetadataExtractor.Formats.Png.PngDirectory.TagTextualData);
|
||||||
|
if (imageHeight is null && imageWidth is null && textualData is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(imageHeight, imageWidth, textualData));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.QuickTimeMovieHeaderDirectory[] GetQuickTimeMovieHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.QuickTimeMovieHeaderDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory> quickTimeMovieHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory in quickTimeMovieHeaderDirectories)
|
||||||
|
{
|
||||||
|
if (quickTimeMovieHeaderDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? created;
|
||||||
|
if (quickTimeMovieHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated, out DateTime checkDateTime))
|
||||||
|
created = checkDateTime;
|
||||||
|
else
|
||||||
|
created = GetDateTime(quickTimeMovieHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeMovieHeaderDirectory.TagCreated));
|
||||||
|
if (created is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(created));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.QuickTimeTrackHeaderDirectory[] GetQuickTimeTrackHeaderDirectoryDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.QuickTimeTrackHeaderDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory> quickTimeTrackHeaderDirectories = directories.OfType<MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory in quickTimeTrackHeaderDirectories)
|
||||||
|
{
|
||||||
|
if (quickTimeTrackHeaderDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
DateTime? created;
|
||||||
|
if (quickTimeTrackHeaderDirectory.TryGetDateTime(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated, out DateTime checkDateTime))
|
||||||
|
created = checkDateTime;
|
||||||
|
else
|
||||||
|
created = GetDateTime(quickTimeTrackHeaderDirectory.GetString(MetadataExtractor.Formats.QuickTime.QuickTimeTrackHeaderDirectory.TagCreated));
|
||||||
|
if (created is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(created));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.WebPDirectory[] GetWebPDirectories(IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
List<Models.Exif.WebPDirectory> results = [];
|
||||||
|
IEnumerable<MetadataExtractor.Formats.WebP.WebPDirectory> webPDirectories = directories.OfType<MetadataExtractor.Formats.WebP.WebPDirectory>();
|
||||||
|
foreach (MetadataExtractor.Formats.WebP.WebPDirectory webPDirectory in webPDirectories)
|
||||||
|
{
|
||||||
|
if (webPDirectory.Tags.Count == 0)
|
||||||
|
continue;
|
||||||
|
string? imageHeight = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageHeight);
|
||||||
|
string? imageWidth = webPDirectory.GetDescription(MetadataExtractor.Formats.WebP.WebPDirectory.TagImageWidth);
|
||||||
|
if (imageHeight is null && imageWidth is null)
|
||||||
|
continue;
|
||||||
|
results.Add(new(imageHeight, imageWidth));
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Models.Exif.ExifDirectory Covert(FileInfo fileInfo, System.Drawing.Size? size, int id, IReadOnlyList<MetadataExtractor.Directory> directories)
|
||||||
|
{
|
||||||
|
Models.Exif.ExifDirectory result;
|
||||||
|
Models.Exif.AviDirectory[] aviDirectories = GetAviDirectories(directories);
|
||||||
|
Models.Exif.GpsDirectory[] gpsDirectories = GetGpsDirectories(directories);
|
||||||
|
Models.Exif.PngDirectory[] pngDirectories = GetPngDirectories(directories);
|
||||||
|
Models.Exif.JpegDirectory[] jpegDirectories = GetJpegDirectories(directories);
|
||||||
|
Models.Exif.WebPDirectory[] webPDirectories = GetWebPDirectories(directories);
|
||||||
|
Models.Exif.ExifDirectoryBase[] exifBaseDirectories = GetExifBaseDirectories(directories);
|
||||||
|
Models.Exif.GifHeaderDirectory[] gifHeaderDirectories = GetGifHeaderDirectories(directories);
|
||||||
|
Models.Exif.MakernoteDirectory[] MakernoteDirectories = GetMakernoteDirectories(directories);
|
||||||
|
Models.Exif.PhotoshopDirectory[] photoshopDirectories = GetPhotoshopDirectories(directories);
|
||||||
|
Models.Exif.FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(fileInfo.FullName, directories);
|
||||||
|
Models.Exif.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories);
|
||||||
|
Models.Exif.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories);
|
||||||
|
result = new(aviDirectories,
|
||||||
|
exifBaseDirectories,
|
||||||
|
fileMetadataDirectories,
|
||||||
|
gifHeaderDirectories,
|
||||||
|
gpsDirectories,
|
||||||
|
size?.Height,
|
||||||
|
id,
|
||||||
|
jpegDirectories,
|
||||||
|
MakernoteDirectories,
|
||||||
|
fileInfo.Name,
|
||||||
|
photoshopDirectories,
|
||||||
|
pngDirectories,
|
||||||
|
quickTimeMovieHeaderDirectories,
|
||||||
|
quickTimeTrackHeaderDirectories,
|
||||||
|
webPDirectories,
|
||||||
|
size?.Width);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Models.Exif.ExifDirectory GetExifDirectory(FileInfo fileInfo)
|
||||||
|
{
|
||||||
|
Models.Exif.ExifDirectory result;
|
||||||
|
int id = 1;
|
||||||
|
System.Drawing.Size? size;
|
||||||
|
try
|
||||||
|
{ size = Dimensions.GetDimensions(fileInfo.FullName); }
|
||||||
|
catch (Exception)
|
||||||
|
{ size = null; }
|
||||||
|
IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(fileInfo.FullName);
|
||||||
|
result = Covert(fileInfo, size, id, directories);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
Helpers/Exif/HelperExif.cs
Normal file
49
Helpers/Exif/HelperExif.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using File_Folder_Helper.Models.Exif;
|
||||||
|
using File_Folder_Helper.Models.Face;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Helpers.Exif;
|
||||||
|
|
||||||
|
internal static class HelperExif
|
||||||
|
{
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<FaceFile> GetCollection(ExifDirectoryBase[]? exifDirectoryBases)
|
||||||
|
{
|
||||||
|
List<FaceFile> results = [];
|
||||||
|
if (exifDirectoryBases is not null)
|
||||||
|
{
|
||||||
|
string? json;
|
||||||
|
FaceFile[]? collection;
|
||||||
|
foreach (ExifDirectoryBase exifDirectoryBase in exifDirectoryBases)
|
||||||
|
{
|
||||||
|
json = exifDirectoryBase.Artist;
|
||||||
|
if (string.IsNullOrEmpty(json))
|
||||||
|
continue;
|
||||||
|
collection = JsonSerializer.Deserialize(json, FaceFileCollectionGenerationContext.Default.FaceFileArray);
|
||||||
|
if (collection is null)
|
||||||
|
continue;
|
||||||
|
results.AddRange(collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DragAndDrop(ILogger<Worker> logger, string argZero)
|
||||||
|
{
|
||||||
|
FileInfo fileInfo = new(argZero);
|
||||||
|
logger.LogInformation("<{argZero}> exists", argZero);
|
||||||
|
ExifDirectory exifDirectory = Exif.GetExifDirectory(fileInfo);
|
||||||
|
ReadOnlyCollection<FaceFile> collection = GetCollection(exifDirectory.ExifBaseDirectories);
|
||||||
|
logger.LogInformation("<{collection}> value", collection.Count);
|
||||||
|
foreach (FaceFile faceFile in collection)
|
||||||
|
{
|
||||||
|
if (faceFile.MappingFromPerson is null)
|
||||||
|
logger.LogInformation("<{Confidence}> value", faceFile.Location?.Confidence);
|
||||||
|
else
|
||||||
|
logger.LogInformation("<{DisplayDirectoryName}> value", faceFile.MappingFromPerson.DisplayDirectoryName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@ public record AppSettings(string Company,
|
|||||||
string[] ExcludeSchemes,
|
string[] ExcludeSchemes,
|
||||||
string PersonBirthdayFormat,
|
string PersonBirthdayFormat,
|
||||||
char[] PersonTitleFilters,
|
char[] PersonTitleFilters,
|
||||||
|
string[] ValidImageFormatExtensions,
|
||||||
string WorkingDirectoryName)
|
string WorkingDirectoryName)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ public class AppSettings
|
|||||||
public string[]? ExcludeSchemes { get; set; }
|
public string[]? ExcludeSchemes { get; set; }
|
||||||
public string? PersonBirthdayFormat { get; set; }
|
public string? PersonBirthdayFormat { get; set; }
|
||||||
public string? PersonTitleFilters { get; set; }
|
public string? PersonTitleFilters { get; set; }
|
||||||
|
public string[]? ValidImageFormatExtensions { get; set; }
|
||||||
public string? WorkingDirectoryName { get; set; }
|
public string? WorkingDirectoryName { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -47,20 +48,20 @@ public class AppSettings
|
|||||||
if (appSettings?.ExcludeSchemes is null) throw new NullReferenceException(nameof(appSettings.ExcludeSchemes));
|
if (appSettings?.ExcludeSchemes is null) throw new NullReferenceException(nameof(appSettings.ExcludeSchemes));
|
||||||
if (appSettings?.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(appSettings.PersonBirthdayFormat));
|
if (appSettings?.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(appSettings.PersonBirthdayFormat));
|
||||||
if (appSettings?.PersonTitleFilters is null) throw new NullReferenceException(nameof(appSettings.PersonTitleFilters));
|
if (appSettings?.PersonTitleFilters is null) throw new NullReferenceException(nameof(appSettings.PersonTitleFilters));
|
||||||
|
if (appSettings?.ValidImageFormatExtensions is null) throw new NullReferenceException(nameof(appSettings.ValidImageFormatExtensions));
|
||||||
if (appSettings?.WorkingDirectoryName is null) throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName));
|
if (appSettings?.WorkingDirectoryName is null) throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName));
|
||||||
result = new(
|
result = new(appSettings.Company,
|
||||||
appSettings.Company,
|
appSettings.DefaultNoteType,
|
||||||
appSettings.DefaultNoteType,
|
appSettings.ExcludeDirectoryNames,
|
||||||
appSettings.ExcludeDirectoryNames,
|
appSettings.ExcludeSchemes,
|
||||||
appSettings.ExcludeSchemes,
|
appSettings.PersonBirthdayFormat,
|
||||||
appSettings.PersonBirthdayFormat,
|
appSettings.PersonTitleFilters.ToArray(),
|
||||||
appSettings.PersonTitleFilters.ToArray(),
|
appSettings.ValidImageFormatExtensions,
|
||||||
appSettings.WorkingDirectoryName
|
appSettings.WorkingDirectoryName);
|
||||||
);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Models.AppSettings Get(IConfigurationRoot configurationRoot)
|
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
|
||||||
{
|
{
|
||||||
Models.AppSettings result;
|
Models.AppSettings result;
|
||||||
#pragma warning disable IL3050, IL2026
|
#pragma warning disable IL3050, IL2026
|
||||||
|
24
Models/Exif/AviDirectory.cs
Normal file
24
Models/Exif/AviDirectory.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record AviDirectory(DateTime? DateTimeOriginal,
|
||||||
|
string? Duration,
|
||||||
|
string? Height,
|
||||||
|
string? Width)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, AviDirectorySourceGenerationContext.Default.AviDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(AviDirectory))]
|
||||||
|
public partial class AviDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
36
Models/Exif/ExifDirectory.cs
Normal file
36
Models/Exif/ExifDirectory.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record ExifDirectory(AviDirectory[] AviDirectories,
|
||||||
|
ExifDirectoryBase[] ExifBaseDirectories,
|
||||||
|
FileMetadataDirectory[] FileMetadataDirectories,
|
||||||
|
GifHeaderDirectory[] GifHeaderDirectories,
|
||||||
|
GpsDirectory[] GpsDirectories,
|
||||||
|
int? Height,
|
||||||
|
int? Id,
|
||||||
|
JpegDirectory[] JpegDirectories,
|
||||||
|
MakernoteDirectory[] MakernoteDirectories,
|
||||||
|
string OriginalFileName,
|
||||||
|
PhotoshopDirectory[] PhotoshopDirectories,
|
||||||
|
PngDirectory[] PngDirectories,
|
||||||
|
QuickTimeMovieHeaderDirectory[] QuickTimeMovieHeaderDirectories,
|
||||||
|
QuickTimeTrackHeaderDirectory[] QuickTimeTrackHeaderDirectories,
|
||||||
|
WebPDirectory[] WebPDirectories,
|
||||||
|
int? Width)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, ExifDirectorySourceGenerationContext.Default.ExifDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonSerializable(typeof(ExifDirectory))]
|
||||||
|
public partial class ExifDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
66
Models/Exif/ExifDirectoryBase.cs
Normal file
66
Models/Exif/ExifDirectoryBase.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record ExifDirectoryBase(string? Aperture,
|
||||||
|
string? ApplicationNotes,
|
||||||
|
string? Artist,
|
||||||
|
string? BitsPerSample,
|
||||||
|
string? BodySerialNumber,
|
||||||
|
string? CameraOwnerName,
|
||||||
|
string? CompressedAverageBitsPerPixel,
|
||||||
|
string? Compression,
|
||||||
|
string? Copyright,
|
||||||
|
DateTime? DateTime,
|
||||||
|
DateTime? DateTimeDigitized,
|
||||||
|
DateTime? DateTimeOriginal,
|
||||||
|
string? DocumentName,
|
||||||
|
string? ExifVersion,
|
||||||
|
string? ExposureTime,
|
||||||
|
string? FileSource,
|
||||||
|
string? ImageDescription,
|
||||||
|
string? ImageHeight,
|
||||||
|
string? ImageNumber,
|
||||||
|
string? ImageUniqueId,
|
||||||
|
string? ImageWidth,
|
||||||
|
string? IsoSpeed,
|
||||||
|
string? LensMake,
|
||||||
|
string? LensModel,
|
||||||
|
string? LensSerialNumber,
|
||||||
|
string? Make,
|
||||||
|
string? MakerNote,
|
||||||
|
string? Model,
|
||||||
|
string? Orientation,
|
||||||
|
int? OrientationValue,
|
||||||
|
string? Rating,
|
||||||
|
string? RatingPercent,
|
||||||
|
string? SecurityClassification,
|
||||||
|
string? ShutterSpeed,
|
||||||
|
string? Software,
|
||||||
|
string? TimeZone,
|
||||||
|
string? TimeZoneDigitized,
|
||||||
|
string? TimeZoneOriginal,
|
||||||
|
string? UserComment,
|
||||||
|
string? WinAuthor,
|
||||||
|
string? WinComment,
|
||||||
|
string? WinKeywords,
|
||||||
|
string? WinSubject,
|
||||||
|
string? WinTitle,
|
||||||
|
string? XResolution,
|
||||||
|
string? YResolution)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, ExifDirectoryBaseSourceGenerationContext.Default.ExifDirectoryBase);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(ExifDirectoryBase))]
|
||||||
|
public partial class ExifDirectoryBaseSourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
23
Models/Exif/FileMetadataDirectory.cs
Normal file
23
Models/Exif/FileMetadataDirectory.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record FileMetadataDirectory(DateTime? FileModifiedDate,
|
||||||
|
string? FileName,
|
||||||
|
string? FileSize)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, FileMetadataDirectorySourceGenerationContext.Default.FileMetadataDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(FileMetadataDirectory))]
|
||||||
|
public partial class FileMetadataDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
22
Models/Exif/GifHeaderDirectory.cs
Normal file
22
Models/Exif/GifHeaderDirectory.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record GifHeaderDirectory(string? ImageHeight,
|
||||||
|
string? ImageWidth)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, GifHeaderDirectorySourceGenerationContext.Default.GifHeaderDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(GifHeaderDirectory))]
|
||||||
|
public partial class GifHeaderDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
26
Models/Exif/GpsDirectory.cs
Normal file
26
Models/Exif/GpsDirectory.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record GpsDirectory(string? Altitude,
|
||||||
|
string? Latitude,
|
||||||
|
string? LatitudeRef,
|
||||||
|
string? Longitude,
|
||||||
|
string? LongitudeRef,
|
||||||
|
DateTime? TimeStamp)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, GpsDirectorySourceGenerationContext.Default.GpsDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(GpsDirectory))]
|
||||||
|
public partial class GpsDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
22
Models/Exif/JpegDirectory.cs
Normal file
22
Models/Exif/JpegDirectory.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record JpegDirectory(string? ImageHeight,
|
||||||
|
string? ImageWidth)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, JpegDirectorySourceGenerationContext.Default.JpegDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(JpegDirectory))]
|
||||||
|
public partial class JpegDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
23
Models/Exif/MakernoteDirectory.cs
Normal file
23
Models/Exif/MakernoteDirectory.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record MakernoteDirectory(string? CameraSerialNumber,
|
||||||
|
string? FirmwareVersion,
|
||||||
|
string? QualityAndFileFormat)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, MakernoteDirectorySourceGenerationContext.Default.MakernoteDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(MakernoteDirectory))]
|
||||||
|
public partial class MakernoteDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
22
Models/Exif/PhotoshopDirectory.cs
Normal file
22
Models/Exif/PhotoshopDirectory.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record PhotoshopDirectory(string? JpegQuality,
|
||||||
|
string? Url)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, PhotoshopDirectorySourceGenerationContext.Default.PhotoshopDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(PhotoshopDirectory))]
|
||||||
|
public partial class PhotoshopDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
23
Models/Exif/PngDirectory.cs
Normal file
23
Models/Exif/PngDirectory.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record PngDirectory(string? ImageHeight,
|
||||||
|
string? ImageWidth,
|
||||||
|
string? TextualData)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, PngDirectorySourceGenerationContext.Default.PngDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(PngDirectory))]
|
||||||
|
public partial class PngDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
21
Models/Exif/QuickTimeMovieHeaderDirectory.cs
Normal file
21
Models/Exif/QuickTimeMovieHeaderDirectory.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record QuickTimeMovieHeaderDirectory(DateTime? Created)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, QuickTimeMovieHeaderDirectorySourceGenerationContext.Default.QuickTimeMovieHeaderDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(QuickTimeMovieHeaderDirectory))]
|
||||||
|
public partial class QuickTimeMovieHeaderDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
21
Models/Exif/QuickTimeTrackHeaderDirectory.cs
Normal file
21
Models/Exif/QuickTimeTrackHeaderDirectory.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record QuickTimeTrackHeaderDirectory(DateTime? Created)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, QuickTimeTrackHeaderDirectorySourceGenerationContext.Default.QuickTimeTrackHeaderDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(QuickTimeTrackHeaderDirectory))]
|
||||||
|
public partial class QuickTimeTrackHeaderDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
22
Models/Exif/WebPDirectory.cs
Normal file
22
Models/Exif/WebPDirectory.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Exif;
|
||||||
|
|
||||||
|
public record WebPDirectory(string? ImageHeight,
|
||||||
|
string? ImageWidth)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, WebPDirectorySourceGenerationContext.Default.WebPDirectory);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(WebPDirectory))]
|
||||||
|
public partial class WebPDirectorySourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
11
Models/Face/FaceEncoding.cs
Normal file
11
Models/Face/FaceEncoding.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
public record FaceEncoding(double[] RawEncoding, int Size);
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = false)]
|
||||||
|
[JsonSerializable(typeof(FaceEncoding))]
|
||||||
|
public partial class FaceEncodingGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
33
Models/Face/FaceFile.cs
Normal file
33
Models/Face/FaceFile.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
public record FaceFile(int? AreaPermyriad,
|
||||||
|
int? ConfidencePercent,
|
||||||
|
string? DMS,
|
||||||
|
DateTime DateTime,
|
||||||
|
FaceEncoding? FaceEncoding,
|
||||||
|
Dictionary<FacePart, FacePoint[]>? FaceParts,
|
||||||
|
Location? Location,
|
||||||
|
string? Maker,
|
||||||
|
MappingFromPerson? MappingFromPerson,
|
||||||
|
string? Model,
|
||||||
|
OutputResolution? OutputResolution);
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = false)]
|
||||||
|
[JsonSerializable(typeof(FaceFile))]
|
||||||
|
public partial class FaceFileGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonSerializable(typeof(FaceFile[]))]
|
||||||
|
public partial class FaceFileCollectionGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonSerializable(typeof(FaceFile[]))]
|
||||||
|
public partial class FaceFileCollectionWriteIndentedGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
54
Models/Face/FacePart.cs
Normal file
54
Models/Face/FacePart.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the part of face.
|
||||||
|
/// </summary>
|
||||||
|
public enum FacePart
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the chin.
|
||||||
|
/// </summary>
|
||||||
|
Chin = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the left eyebrow.
|
||||||
|
/// </summary>
|
||||||
|
LeftEyebrow = 17,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the right eyebrow.
|
||||||
|
/// </summary>
|
||||||
|
RightEyebrow = 22,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the nose bridge.
|
||||||
|
/// </summary>
|
||||||
|
NoseBridge = 27,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the nose tip.
|
||||||
|
/// </summary>
|
||||||
|
NoseTip = 31,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the left eye.
|
||||||
|
/// </summary>
|
||||||
|
LeftEye = 36,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the right eye.
|
||||||
|
/// </summary>
|
||||||
|
RightEye = 42,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the top lip.
|
||||||
|
/// </summary>
|
||||||
|
TopLip = 48,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the bottom lip.
|
||||||
|
/// </summary>
|
||||||
|
BottomLip = 55
|
||||||
|
|
||||||
|
}
|
39
Models/Face/FacePoint.cs
Normal file
39
Models/Face/FacePoint.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
[method: JsonConstructor]
|
||||||
|
public class FacePoint(int index, int x, int y)
|
||||||
|
{
|
||||||
|
public int Index { get; } = index;
|
||||||
|
public int X { get; } = x;
|
||||||
|
public int Y { get; } = y;
|
||||||
|
|
||||||
|
private readonly Point _Point = new(x, y);
|
||||||
|
|
||||||
|
public override bool Equals(object? obj) => obj is FacePoint point && Equals(point);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0070
|
||||||
|
public override int GetHashCode()
|
||||||
|
#pragma warning restore IDE0070
|
||||||
|
{
|
||||||
|
int hashCode = 1861411795;
|
||||||
|
hashCode = (hashCode * -1521134295) + _Point.GetHashCode();
|
||||||
|
hashCode = (hashCode * -1521134295) + Index.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(FacePoint? facePoint)
|
||||||
|
{
|
||||||
|
return facePoint is not null
|
||||||
|
&& X == facePoint.X
|
||||||
|
&& Y == facePoint.Y
|
||||||
|
&& Index == facePoint.Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(FacePoint point1, FacePoint point2) => point1.Equals(point2);
|
||||||
|
|
||||||
|
public static bool operator !=(FacePoint point1, FacePoint point2) => !(point1 == point2);
|
||||||
|
|
||||||
|
}
|
42
Models/Face/Location.cs
Normal file
42
Models/Face/Location.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
[method: JsonConstructor]
|
||||||
|
public class Location(int bottom, double confidence, int left, int right, int top) : IEquatable<Location>
|
||||||
|
{
|
||||||
|
|
||||||
|
public int Bottom { init; get; } = bottom;
|
||||||
|
public double Confidence { init; get; } = confidence;
|
||||||
|
public int Left { init; get; } = left;
|
||||||
|
public int Right { init; get; } = right;
|
||||||
|
public int Top { init; get; } = top;
|
||||||
|
|
||||||
|
public override bool Equals(object? obj) => Equals(obj as Location);
|
||||||
|
|
||||||
|
#pragma warning disable IDE0070
|
||||||
|
public override int GetHashCode()
|
||||||
|
#pragma warning restore IDE0070
|
||||||
|
{
|
||||||
|
int hashCode = -773114317;
|
||||||
|
hashCode = (hashCode * -1521134295) + Bottom.GetHashCode();
|
||||||
|
hashCode = (hashCode * -1521134295) + Left.GetHashCode();
|
||||||
|
hashCode = (hashCode * -1521134295) + Right.GetHashCode();
|
||||||
|
hashCode = (hashCode * -1521134295) + Top.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Location? location)
|
||||||
|
{
|
||||||
|
return location is not null
|
||||||
|
&& Bottom == location.Bottom
|
||||||
|
&& Left == location.Left
|
||||||
|
&& Right == location.Right
|
||||||
|
&& Top == location.Top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Location location1, Location location2) => EqualityComparer<Location>.Default.Equals(location1, location2);
|
||||||
|
|
||||||
|
public static bool operator !=(Location location1, Location location2) => !(location1 == location2);
|
||||||
|
|
||||||
|
}
|
24
Models/Face/MappingFromPerson.cs
Normal file
24
Models/Face/MappingFromPerson.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
public record MappingFromPerson(int? ApproximateYears,
|
||||||
|
string DisplayDirectoryName,
|
||||||
|
long PersonKey,
|
||||||
|
string SegmentB)
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = JsonSerializer.Serialize(this, MappingFromPersonGenerationContext.Default.MappingFromPerson);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(MappingFromPerson))]
|
||||||
|
public partial class MappingFromPersonGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
}
|
5
Models/Face/OutputResolution.cs
Normal file
5
Models/Face/OutputResolution.cs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
namespace File_Folder_Helper.Models.Face;
|
||||||
|
|
||||||
|
public record OutputResolution(int Height,
|
||||||
|
int Orientation,
|
||||||
|
int Width);
|
@ -136,6 +136,7 @@ public class Worker : BackgroundService
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
string extension = Path.GetExtension(_Args[0]);
|
||||||
if (consoleKey is not ConsoleKey.End && !_ConsoleKeys.Contains(consoleKey))
|
if (consoleKey is not ConsoleKey.End && !_ConsoleKeys.Contains(consoleKey))
|
||||||
consoleKey = ConsoleKey.End;
|
consoleKey = ConsoleKey.End;
|
||||||
if (singleCharIndex is not null)
|
if (singleCharIndex is not null)
|
||||||
@ -233,6 +234,8 @@ public class Worker : BackgroundService
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (_AppSettings.ValidImageFormatExtensions.Contains(extension) && File.Exists(_Args[0]))
|
||||||
|
Helpers.Exif.HelperExif.DragAndDrop(_Logger, _Args[0]);
|
||||||
else
|
else
|
||||||
throw new Exception(_Args[0]);
|
throw new Exception(_Args[0]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user