题
我正在从一个服务下载一些图像,该服务并不总是包含内容类型,并且不提供我正在下载的文件的扩展名(呃,不要问)。
确定 .NET 中图像格式的最佳方法是什么?
读取这些下载图像的应用程序需要有正确的文件扩展名,否则一切都会崩溃。
解决方案
一种可能更简单的方法是使用 Image.FromFile(),然后使用 RawFormat 属性,因为它已经知道最常见格式的标头中的魔术位,如下所示:
Image i = Image.FromFile("c:\\foo");
if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(i.RawFormat))
MessageBox.Show("JPEG");
else if (System.Drawing.Imaging.ImageFormat.Gif.Equals(i.RawFormat))
MessageBox.Show("GIF");
//Same for the rest of the formats
其他提示
所有图像格式将其初始字节设置为特定值:
- .JPG: 0xFF 0xD8
- 巴布亚新几内亚: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- 动图: 'G' '我' 'F'
搜索“jpg 文件格式”,将 jpg 替换为您需要识别的其他文件格式。
正如 Garth 所建议的,有一个 这种“神奇数字”的数据库 显示许多文件的文件类型。如果您必须检测许多不同的文件类型,则值得仔细查看以查找所需的信息。如果您确实需要扩展它以涵盖许多很多文件类型,请查看相关的 文件命令 它实现了正确使用数据库的引擎(对于许多文件格式来说这并不简单,并且几乎是一个统计过程)
-亚当
您可以使用下面的代码,而无需引用 System.Drawing 和不必要的对象 Image 创建。您也可以使用 亚历克斯 即使没有 System.IO 的流和引用也能解决此问题。
public enum ImageFormat
{
bmp,
jpeg,
gif,
tiff,
png,
unknown
}
public static ImageFormat GetImageFormat(Stream stream)
{
// see http://www.mikekunz.com/image_file_header.html
var bmp = Encoding.ASCII.GetBytes("BM"); // BMP
var gif = Encoding.ASCII.GetBytes("GIF"); // GIF
var png = new byte[] { 137, 80, 78, 71 }; // PNG
var tiff = new byte[] { 73, 73, 42 }; // TIFF
var tiff2 = new byte[] { 77, 77, 42 }; // TIFF
var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon
var buffer = new byte[4];
stream.Read(buffer, 0, buffer.Length);
if (bmp.SequenceEqual(buffer.Take(bmp.Length)))
return ImageFormat.bmp;
if (gif.SequenceEqual(buffer.Take(gif.Length)))
return ImageFormat.gif;
if (png.SequenceEqual(buffer.Take(png.Length)))
return ImageFormat.png;
if (tiff.SequenceEqual(buffer.Take(tiff.Length)))
return ImageFormat.tiff;
if (tiff2.SequenceEqual(buffer.Take(tiff2.Length)))
return ImageFormat.tiff;
if (jpeg.SequenceEqual(buffer.Take(jpeg.Length)))
return ImageFormat.jpeg;
if (jpeg2.SequenceEqual(buffer.Take(jpeg2.Length)))
return ImageFormat.jpeg;
return ImageFormat.unknown;
}
亚当所指的方向完全正确。
如果您想了解如何 感知几乎任何文件, ,查看后面的数据库 file
UNIX、Linux 或 Mac OS X 计算机上的命令。
file
使用“幻数”数据库(亚当列出的初始字节)来感知文件的类型。 man file
会告诉你在你的机器上哪里可以找到数据库,例如 /usr/share/file/magic
. man magic
会告诉你它的 格式.
您可以根据在数据库中看到的内容编写自己的检测代码,使用预打包的库(例如 python 魔法),或者 - 如果你是 真的 冒险的 — 实现 .NET 版本 libmagic
. 。没找到,希望有大佬指点一下。
如果您手边没有 UNIX 机器,数据库如下所示:
# PNG [Portable Network Graphics, or "PNG's Not GIF"] images # (Greg Roelofs, newt@uchicago.edu) # (Albert Cahalan, acahalan@cs.uml.edu) # # 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ... # 0 string \x89PNG PNG image data, >4 belong !0x0d0a1a0a CORRUPTED, >4 belong 0x0d0a1a0a >>16 belong x %ld x >>20 belong x %ld, >>24 byte x %d-bit >>25 byte 0 grayscale, >>25 byte 2 \b/color RGB, >>25 byte 3 colormap, >>25 byte 4 gray+alpha, >>25 byte 6 \b/color RGBA, #>>26 byte 0 deflate/32K, >>28 byte 0 non-interlaced >>28 byte 1 interlaced 1 string PNG PNG image data, CORRUPTED # GIF 0 string GIF8 GIF image data >4 string 7a \b, version 8%s, >4 string 9a \b, version 8%s, >6 leshort >0 %hd x >8 leshort >0 %hd #>10 byte &0x80 color mapped, #>10 byte&0x07 =0x00 2 colors #>10 byte&0x07 =0x01 4 colors #>10 byte&0x07 =0x02 8 colors #>10 byte&0x07 =0x03 16 colors #>10 byte&0x07 =0x04 32 colors #>10 byte&0x07 =0x05 64 colors #>10 byte&0x07 =0x06 128 colors #>10 byte&0x07 =0x07 256 colors
祝你好运!
有一种编程方法可以确定图像 MIMETYPE。
有课 系统.绘图.成像.ImageCodecInfo.
这个类有属性 Mime类型 和 格式ID. 。它还有一个方法 获取图像编码器 它返回所有图像编码器的集合。创建按格式 id 索引的 mime 类型字典很容易。
班级 系统.绘图.图像 有财产 原始格式 类型 系统.绘图.成像.ImageFormat 拥有财产的 指导 这相当于财产 格式ID 班级的 系统.绘图.成像.ImageCodecInfo, ,这是从字典中获取 MIMETYPE 的关键。
例子:
创建 mime 类型字典的静态方法
static Dictionary<Guid, string> GetImageFormatMimeTypeIndex()
{
Dictionary<Guid, string> ret = new Dictionary<Guid, string>();
var encoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
foreach(var e in encoders)
{
ret.Add(e.FormatID, e.MimeType);
}
return ret;
}
使用:
Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();
FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid];