Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
0ec6443270 |
@ -8,16 +8,16 @@ internal static class Dimensions
|
|||||||
#pragma warning disable IDE0230
|
#pragma warning disable IDE0230
|
||||||
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||||
{
|
{
|
||||||
|
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||||
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||||
|
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
||||||
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
||||||
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
|
||||||
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
|
||||||
};
|
};
|
||||||
#pragma warning restore IDE0230
|
#pragma warning restore IDE0230
|
||||||
|
|
||||||
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < thatBytes.Length; i += 1)
|
for (int i = 0; i < thatBytes.Length; i += 1)
|
||||||
{
|
{
|
||||||
@ -103,24 +103,41 @@ internal static class Dimensions
|
|||||||
|
|
||||||
internal static Size? GetDimensions(BinaryReader binaryReader)
|
internal static Size? GetDimensions(BinaryReader binaryReader)
|
||||||
{
|
{
|
||||||
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
|
Size? result;
|
||||||
byte[] magicBytes = new byte[maxMagicBytesLength];
|
List<byte> magicBytes = [];
|
||||||
for (int i = 0; i < maxMagicBytesLength; i += 1)
|
int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
|
||||||
|
if (magicBytesLengths.Length == 0)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
magicBytes[i] = binaryReader.ReadByte();
|
result = null;
|
||||||
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
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))
|
magicBytes.Add(binaryReader.ReadByte());
|
||||||
return kvPair.Value(binaryReader);
|
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)
|
internal static Size? GetDimensions(string path)
|
||||||
{
|
{
|
||||||
using BinaryReader binaryReader = new(File.OpenRead(path));
|
Size? result;
|
||||||
return GetDimensions(binaryReader);
|
using FileStream fileStream = File.OpenRead(path);
|
||||||
|
using BinaryReader binaryReader = new(fileStream);
|
||||||
|
result = GetDimensions(binaryReader);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -76,7 +76,7 @@ public class FaceFileSystem : FileSystem, Properties.IFaceFileSystem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
System.Drawing.Size size = Stateless.Methods.ImageHelper.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
|
System.Drawing.Size size = Stateless.Methods.Dimensions.GetDimensions(fileInfo.FullName, faceRight, faceBottom);
|
||||||
imageWidth = size.Width;
|
imageWidth = size.Width;
|
||||||
imageHeight = size.Height;
|
imageHeight = size.Height;
|
||||||
}
|
}
|
||||||
|
149
Shared/Models/Stateless/Methods/Dimensions.cs
Normal file
149
Shared/Models/Stateless/Methods/Dimensions.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
||||||
|
|
||||||
|
internal static class Dimensions
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma warning disable IDE0230
|
||||||
|
private static readonly Dictionary<byte[], Func<BinaryReader, Size?>> _ImageFormatDecoders = new()
|
||||||
|
{
|
||||||
|
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
||||||
|
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
||||||
|
{ new byte[] { 0x52, 0x49, 0x46, 0x46 }, DecodeWebP },
|
||||||
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
||||||
|
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
||||||
|
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
||||||
|
};
|
||||||
|
#pragma warning restore IDE0230
|
||||||
|
|
||||||
|
private static bool StartsWith(List<byte> thisBytes, byte[] thatBytes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < thatBytes.Length; i += 1)
|
||||||
|
{
|
||||||
|
if (thisBytes[i] == thatBytes[i])
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static short ReadLittleEndianInt16(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[sizeof(short)];
|
||||||
|
for (int i = 0; i < sizeof(short); i += 1)
|
||||||
|
bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
|
||||||
|
return BitConverter.ToInt16(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ReadLittleEndianInt32(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[sizeof(int)];
|
||||||
|
for (int i = 0; i < sizeof(int); i += 1)
|
||||||
|
bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
|
||||||
|
return BitConverter.ToInt32(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeBitmap(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadBytes(16);
|
||||||
|
int width = binaryReader.ReadInt32();
|
||||||
|
int height = binaryReader.ReadInt32();
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeGif(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
int width = binaryReader.ReadInt16();
|
||||||
|
int height = binaryReader.ReadInt16();
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodePng(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadBytes(8);
|
||||||
|
int width = ReadLittleEndianInt32(binaryReader);
|
||||||
|
int height = ReadLittleEndianInt32(binaryReader);
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeJfif(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
while (binaryReader.ReadByte() == 0xff)
|
||||||
|
{
|
||||||
|
byte marker = binaryReader.ReadByte();
|
||||||
|
short chunkLength = ReadLittleEndianInt16(binaryReader);
|
||||||
|
if (marker == 0xc0)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadByte();
|
||||||
|
int height = ReadLittleEndianInt16(binaryReader);
|
||||||
|
int width = ReadLittleEndianInt16(binaryReader);
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
if (chunkLength >= 0)
|
||||||
|
_ = binaryReader.ReadBytes(chunkLength - 2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ushort uChunkLength = (ushort)chunkLength;
|
||||||
|
_ = binaryReader.ReadBytes(uChunkLength - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Size? DecodeWebP(BinaryReader binaryReader)
|
||||||
|
{
|
||||||
|
_ = binaryReader.ReadUInt32(); // Size
|
||||||
|
_ = binaryReader.ReadBytes(15); // WEBP, VP8 + more
|
||||||
|
_ = binaryReader.ReadBytes(3); // SYNC
|
||||||
|
int width = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits width
|
||||||
|
int height = binaryReader.ReadUInt16() & 0b00_11111111111111; // 14 bits height
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Size GetDimensions(BinaryReader binaryReader, int? faceRight, int? faceBottom)
|
||||||
|
{
|
||||||
|
Size? result;
|
||||||
|
List<byte> magicBytes = [];
|
||||||
|
int[] magicBytesLengths = (from l in _ImageFormatDecoders.Keys where l.Length <= binaryReader.BaseStream.Length orderby l.Length descending select l.Length).ToArray();
|
||||||
|
if (magicBytesLengths.Length == 0)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
if (binaryReader.BaseStream.Length == binaryReader.BaseStream.Position)
|
||||||
|
_ = binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
for (int i = 0; i < magicBytesLengths[0]; i++)
|
||||||
|
{
|
||||||
|
magicBytes.Add(binaryReader.ReadByte());
|
||||||
|
foreach (KeyValuePair<byte[], Func<BinaryReader, Size?>> kvPair in _ImageFormatDecoders)
|
||||||
|
{
|
||||||
|
if (StartsWith(magicBytes, kvPair.Key))
|
||||||
|
{
|
||||||
|
result = kvPair.Value(binaryReader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result is not null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result is null)
|
||||||
|
{
|
||||||
|
if (faceRight is null || faceBottom is null)
|
||||||
|
throw new Exception("face is null!");
|
||||||
|
result = new(faceRight.Value, faceBottom.Value);
|
||||||
|
}
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Size GetDimensions(string path, int? faceRight, int? faceBottom)
|
||||||
|
{
|
||||||
|
Size result;
|
||||||
|
using FileStream fileStream = File.OpenRead(path);
|
||||||
|
using BinaryReader binaryReader = new(fileStream);
|
||||||
|
result = GetDimensions(binaryReader, faceRight, faceBottom);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,132 +0,0 @@
|
|||||||
using System.Drawing;
|
|
||||||
|
|
||||||
namespace View_by_Distance.Shared.Models.Stateless.Methods;
|
|
||||||
|
|
||||||
internal abstract class ImageHelper
|
|
||||||
{
|
|
||||||
|
|
||||||
private static bool StartsWith(byte[] thisBytes, byte[] thatBytes)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < thatBytes.Length; i += 1)
|
|
||||||
{
|
|
||||||
if (thisBytes[i] != thatBytes[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static short ReadLittleEndianInt16(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
byte[] bytes = new byte[sizeof(short)];
|
|
||||||
for (int i = 0; i < sizeof(short); i += 1)
|
|
||||||
bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte();
|
|
||||||
return BitConverter.ToInt16(bytes, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int ReadLittleEndianInt32(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
byte[] bytes = new byte[sizeof(int)];
|
|
||||||
for (int i = 0; i < sizeof(int); i += 1)
|
|
||||||
bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte();
|
|
||||||
return BitConverter.ToInt32(bytes, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Size DecodeBitmap(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
_ = binaryReader.ReadBytes(16);
|
|
||||||
int width = binaryReader.ReadInt32();
|
|
||||||
int height = binaryReader.ReadInt32();
|
|
||||||
return new Size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Size DecodeGif(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
int width = binaryReader.ReadInt16();
|
|
||||||
int height = binaryReader.ReadInt16();
|
|
||||||
return new Size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Size DecodePng(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
_ = binaryReader.ReadBytes(8);
|
|
||||||
int width = ReadLittleEndianInt32(binaryReader);
|
|
||||||
int height = ReadLittleEndianInt32(binaryReader);
|
|
||||||
return new Size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Size DecodeJfif(BinaryReader binaryReader)
|
|
||||||
{
|
|
||||||
while (binaryReader.ReadByte() == 0xff)
|
|
||||||
{
|
|
||||||
byte marker = binaryReader.ReadByte();
|
|
||||||
short chunkLength = ReadLittleEndianInt16(binaryReader);
|
|
||||||
if (marker == 0xc0)
|
|
||||||
{
|
|
||||||
_ = binaryReader.ReadByte();
|
|
||||||
int height = ReadLittleEndianInt16(binaryReader);
|
|
||||||
int width = ReadLittleEndianInt16(binaryReader);
|
|
||||||
return new Size(width, height);
|
|
||||||
}
|
|
||||||
_ = binaryReader.ReadBytes(chunkLength - 2);
|
|
||||||
}
|
|
||||||
throw new ArgumentException("Could not recognize image format.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dimensions of an image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the image to get the dimensions of.</param>
|
|
||||||
/// <returns>The dimensions of the specified image.</returns>
|
|
||||||
/// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
|
|
||||||
internal static Size GetDimensions(BinaryReader binaryReader, int? faceRight, int? faceBottom)
|
|
||||||
{
|
|
||||||
Size? result = null;
|
|
||||||
#pragma warning disable IDE0230
|
|
||||||
Dictionary<byte[], Func<BinaryReader, Size>> _ImageFormatDecoders = new()
|
|
||||||
{
|
|
||||||
{ new byte[] { 0x42, 0x4D }, DecodeBitmap },
|
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
|
|
||||||
{ new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
|
|
||||||
{ new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
|
|
||||||
{ new byte[] { 0xff, 0xd8 }, DecodeJfif },
|
|
||||||
};
|
|
||||||
#pragma warning restore IDE0230
|
|
||||||
int maxMagicBytesLength = _ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
|
|
||||||
byte[] magicBytes = new byte[maxMagicBytesLength];
|
|
||||||
for (int i = 0; i < maxMagicBytesLength; i += 1)
|
|
||||||
{
|
|
||||||
magicBytes[i] = binaryReader.ReadByte();
|
|
||||||
foreach (KeyValuePair<byte[], Func<BinaryReader, Size>> kvPair in _ImageFormatDecoders)
|
|
||||||
{
|
|
||||||
if (!StartsWith(magicBytes, kvPair.Key))
|
|
||||||
continue;
|
|
||||||
result = kvPair.Value(binaryReader);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (result is not null)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (result is null)
|
|
||||||
{
|
|
||||||
if (faceRight is null || faceBottom is null)
|
|
||||||
throw new Exception("face is null!");
|
|
||||||
result = new(faceRight.Value, faceBottom.Value);
|
|
||||||
}
|
|
||||||
return result.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dimensions of an image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the image to get the dimensions of.</param>
|
|
||||||
/// <returns>The dimensions of the specified image.</returns>
|
|
||||||
/// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
|
|
||||||
internal static Size GetDimensions(string path, int? faceRight, int? faceBottom)
|
|
||||||
{
|
|
||||||
Size result;
|
|
||||||
using BinaryReader binaryReader = new(File.OpenRead(path));
|
|
||||||
result = GetDimensions(binaryReader, faceRight, faceBottom);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Reference in New Issue
Block a user