This commit is contained in:
2025-06-30 16:33:14 -07:00
parent c7ded16e50
commit 5d11335eda
38 changed files with 901 additions and 960 deletions

View File

@ -1,70 +0,0 @@
using System.Globalization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Metadata.Models.Stateless.Methods;
internal static class Base
{
internal static string? GetMaker(ExifDirectoryBase[]? exifBaseDirectories)
{
string? result = null;
if (exifBaseDirectories is not null)
{
string value;
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
value = exifDirectoryBase?.Make is null ? string.Empty : exifDirectoryBase.Make.ToString().Trim();
if (string.IsNullOrEmpty(value))
result = null;
else
{
result = $"{value[0].ToString().ToUpper()}{value[1..].ToLower()}";
break;
}
}
}
return result;
}
internal static string? GetModel(ExifDirectoryBase[]? exifBaseDirectories)
{
string? result = null;
if (exifBaseDirectories is not null)
{
string value;
foreach (ExifDirectoryBase exifDirectoryBase in exifBaseDirectories)
{
value = exifDirectoryBase?.Model is null ? string.Empty : exifDirectoryBase.Model.ToString().Trim();
if (string.IsNullOrEmpty(value))
result = null;
else
{
result = value;
break;
}
}
}
return result;
}
#pragma warning restore CA1416
internal static DateTime? GetDateTime(string dateTimeFormat, string? value)
{
DateTime? result;
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;
}
#pragma warning disable CA1416
}

View File

@ -8,18 +8,18 @@ internal static class Dimensions
#pragma warning disable IDE0230
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
{
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
};
#pragma warning restore IDE0230
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
{
for (int i = 0; i < thatBytes.Length; i += 1)
for (int i = 0; i < thisBytes.Count && i < thatBytes.Length; i += 1)
{
if (thisBytes[i] == thatBytes[i])
continue;
@ -103,24 +103,41 @@ internal static class Dimensions
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)
Size? result;
List<byte> magicBytes = [];
int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
if (magicBytesLengths.Length == 0)
result = null;
else
{
magicBytes[i] = binaryReader.ReadByte();
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
result = null;
if (binaryReader.BaseStream.Length == binaryReader.BaseStream.Position)
_ = binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
for (int i = 0; i < magicBytesLengths[0]; i++)
{
if (StartsWith(magicBytes, kvPair.Key))
return kvPair.Value(binaryReader);
magicBytes.Add(binaryReader.ReadByte());
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
{
if (StartsWith(magicBytes, kvPair.Key))
{
result = kvPair.Value(binaryReader);
break;
}
}
if (result is not null)
break;
}
}
return null;
return result;
}
internal static Size? GetDimensions(string path)
{
using BinaryReader binaryReader = new(File.OpenRead(path));
return GetDimensions(binaryReader);
Size? result;
using FileStream fileStream = File.OpenRead(path);
using BinaryReader binaryReader = new(fileStream);
result = GetDimensions(binaryReader);
return result;
}
}

View File

@ -75,9 +75,11 @@ internal abstract class Exif
string? fileSource = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagFileSource);
string? imageDescription = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageDescription);
string? imageHeight = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageHeight);
int? imageHeightValue = imageHeight is null ? null : exifDirectoryBase.GetInt32(ExifDirectoryBase.TagImageHeight);
string? imageNumber = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageNumber);
string? imageUniqueId = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageUniqueId);
string? imageWidth = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagImageWidth);
int? imageWidthValue = imageWidth is null ? null : exifDirectoryBase.GetInt32(ExifDirectoryBase.TagImageWidth);
string? isoSpeed = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagIsoSpeed);
string? lensMake = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensMake);
string? lensModel = exifDirectoryBase.GetDescription(ExifDirectoryBase.TagLensModel);
@ -164,52 +166,54 @@ internal abstract class Exif
&& 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));
results.Add(new(Aperture: aperture,
ApplicationNotes: applicationNotes,
Artist: artist,
BitsPerSample: bitsPerSample,
BodySerialNumber: bodySerialNumber,
CameraOwnerName: cameraOwnerName,
CompressedAverageBitsPerPixel: compressedAverageBitsPerPixel,
Compression: compression,
Copyright: copyright,
DateTime: dateTime,
DateTimeDigitized: dateTimeDigitized,
DateTimeOriginal: dateTimeOriginal,
DocumentName: documentName,
ExifVersion: exifVersion,
ExposureTime: exposureTime,
FileSource: fileSource,
ImageDescription: imageDescription,
ImageHeight: imageHeight,
ImageHeightValue: imageHeightValue,
ImageNumber: imageNumber,
ImageUniqueId: imageUniqueId,
ImageWidth: imageWidth,
ImageWidthValue: imageWidthValue,
IsoSpeed: isoSpeed,
LensMake: lensMake,
LensModel: lensModel,
LensSerialNumber: lensSerialNumber,
Make: make,
MakerNote: makerNote,
Model: model,
Orientation: orientation,
OrientationValue: orientationValue,
Rating: rating,
RatingPercent: ratingPercent,
SecurityClassification: securityClassification,
ShutterSpeed: shutterSpeed,
Software: software,
TimeZone: timeZone,
TimeZoneDigitized: timeZoneDigitized,
TimeZoneOriginal: timeZoneOriginal,
UserComment: userComment,
WinAuthor: winAuthor,
WinComment: winComment,
WinKeywords: winKeywords,
WinSubject: winSubject,
WinTitle: winTitle,
XResolution: xResolution,
YResolution: yResolution));
}
return results.ToArray();
}
@ -499,21 +503,21 @@ internal abstract class Exif
Shared.Models.FileMetadataDirectory[] fileMetadataDirectories = GetFileMetadataDirectories(filePath.FullName, directories);
Shared.Models.QuickTimeMovieHeaderDirectory[] quickTimeMovieHeaderDirectories = GetQuickTimeMovieHeaderDirectoryDirectories(directories);
Shared.Models.QuickTimeTrackHeaderDirectory[] quickTimeTrackHeaderDirectories = GetQuickTimeTrackHeaderDirectoryDirectories(directories);
result = new(aviDirectories,
exifBaseDirectories,
fileMetadataDirectories,
filePath,
gifHeaderDirectories,
gpsDirectories,
size?.Height,
jpegDirectories,
makernoteDirectories,
photoshopDirectories,
pngDirectories,
quickTimeMovieHeaderDirectories,
quickTimeTrackHeaderDirectories,
webPDirectories,
size?.Width);
result = new(AviDirectories: aviDirectories,
ExifBaseDirectories: exifBaseDirectories,
FileMetadataDirectories: fileMetadataDirectories,
FilePath: filePath,
GifHeaderDirectories: gifHeaderDirectories,
GpsDirectories: gpsDirectories,
Height: size?.Height ?? Shared.Models.Stateless.Methods.IMetaBase.GetHeight(exifBaseDirectories),
JpegDirectories: jpegDirectories,
MakernoteDirectories: makernoteDirectories,
PhotoshopDirectories: photoshopDirectories,
PngDirectories: pngDirectories,
QuickTimeMovieHeaderDirectories: quickTimeMovieHeaderDirectories,
QuickTimeTrackHeaderDirectories: quickTimeTrackHeaderDirectories,
WebPDirectories: webPDirectories,
Width: size?.Width ?? Shared.Models.Stateless.Methods.IMetaBase.GetWidth(exifBaseDirectories));
return result;
}

View File

@ -19,16 +19,6 @@ public interface IMetadata
static ExifDirectory GetExifDirectory(FilePath filePath) =>
Exif.GetExifDirectory(filePath);
string? TestStatic_GetMaker(ExifDirectory? exifDirectory) =>
GetMaker(exifDirectory);
static string? GetMaker(ExifDirectory? exifDirectory) =>
Base.GetMaker(exifDirectory?.ExifBaseDirectories);
string? TestStatic_GetModel(ExifDirectory? exifDirectory) =>
GetModel(exifDirectory);
static string? GetModel(ExifDirectory? exifDirectory) =>
Base.GetModel(exifDirectory?.ExifBaseDirectories);
string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) =>
GetOutputResolution(exifDirectory);
static string? GetOutputResolution(ExifDirectory? exifDirectory) =>
@ -64,14 +54,4 @@ public interface IMetadata
// static Dictionary<string, MetadataExtractorDirectory> GetMetadataCollection(FileInfo fileInfo, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions) =>
// Metadata.GetMetadataCollection(fileInfo, subFileTuples, parseExceptions);
string TestStatic_DateTimeFormat() =>
DateTimeFormat();
static string DateTimeFormat() =>
"yyyy:MM:dd HH:mm:ss";
DateTime? TestStatic_GetDateTime(string dateTimeFormat, string? value) =>
GetDateTime(dateTimeFormat, value);
static DateTime? GetDateTime(string dateTimeFormat, string? value) =>
Base.GetDateTime(dateTimeFormat, value);
}