图片文件幻数
关于JPEG格式
二进制形式打开文件,文件开始字节为FF D8,文件结束两字节为FF D9
JPEG 文件有两种不同的元数据格式:JFIF 和 EXIF。
JFIF 以 ff d8 ff e0 开头,EXIF 以 ff d8 ff e1 开头。
代码示例
private static readonly byte[] Bmp = { 66, 77 };
private static readonly byte[] Jpeg = { 255, 216, 255 }; //第四位可能是224,也可能是225
private static readonly byte[] Gif = { 71, 73, 70, 56 };
private static readonly byte[] Tiff1 = { 77, 77, 00, 42 }; //TIFF format (Motorola - big endian)
private static readonly byte[] Tiff2 = { 73, 73, 42, 00 }; //TIFF format (Intel - little endian)
private static readonly byte[] Png = { 137, 80, 78, 71 };
private static readonly byte[] WebPRiff = { 82, 73, 70, 70 }; // 'RIFF'
private static readonly byte[] WebPWebP = { 87, 69, 66, 80 }; // 'WEBP'
private const int BufferLength = 12; // webp 需要这么长
/// <summary>
/// 解析入口
/// </summary>
/// <param name="stream">图片文件数据流</param>
/// <returns></returns>
public static ImageFormat GetImageFormat(Stream stream)
{
var bytes = new byte[BufferLength];
var read = stream.Read(bytes, 0, bytes.Length);
return read < BufferLength ? ImageFormat.Unknown : GetImageFormat(bytes);
}
/// <summary>
/// 获取文件格式类型
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static ImageFormat GetImageFormat(byte[] bytes)
{
if (bytes.Length < BufferLength)
return ImageFormat.Unknown;
if (bytes.Take(Bmp.Length).SequenceEqual(Bmp))
return ImageFormat.Bmp;
if (bytes.Take(Jpeg.Length).SequenceEqual(Jpeg))
return ImageFormat.Jpeg;
if (bytes.Take(Gif.Length).SequenceEqual(Gif))
return ImageFormat.Gif;
if (bytes.Take(Tiff1.Length).SequenceEqual(Tiff1)
|| bytes.Take(Tiff2.Length).SequenceEqual(Tiff2))
return ImageFormat.Tiff;
if (bytes.Take(Png.Length).SequenceEqual(Png))
return ImageFormat.Png;
if (bytes.Take(WebPRiff.Length).SequenceEqual(WebPRiff)
&& bytes.Skip(8).Take(WebPWebP.Length).SequenceEqual(WebPWebP))
return ImageFormat.WebP;
return ImageFormat.Unknown;
}
源码传送门