确定图像的文件types
我正在从一个服务中下载一些图片,这些图片并不总是包含内容types,也没有提供我下载的文件的扩展名(呃,不要问)。
在.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
- PNG: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- GIF: 'G''我'F'
search“jpg文件格式”replace为您需要识别的其他文件格式的JPG。
正如Garth所build议的,有一个这样的“幻数”数据库,显示了许多文件的文件types。 如果你必须检测许多不同的文件types,那么通过查找你需要的信息是值得的。 如果你确实需要扩展到覆盖很多文件types的话,可以看一下实现引擎的关联文件命令来正确使用数据库(这对许多文件格式来说是不重要的,而且几乎是一个统计过程)
-亚当
您可以使用下面的代码,而无需引用System.Drawing和对象Image的不必要的创build。 即使没有System.IO的stream和引用,您也可以使用Alex解决scheme。
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; }
亚当正指着正确的方向。
如果您想了解如何检测几乎任何文件 ,请在UNIX,Linux或Mac OS X机器上查看file
命令后面的数据库。
file
使用“幻数”数据库 – 亚当列出的最初字节 – 来检测文件的types。 man file
会告诉你在哪里可以find你机器上的数据库,例如/usr/share/file/magic
。 man magic
将会告诉你它的格式 。
您可以根据您在数据库中看到的内容编写自己的检测代码,使用预先打包的库(例如python-magic ),或者 – 如果您确实冒险 – 实现.NET版本的libmagic
。 我找不到一个,希望另一个成员能指出一个。
如果你没有一台UNIX机器,数据库看起来像这样:
#PNG [便携式networkinggraphics,或“PNG的非GIF”]图像 #(Greg Roelofs,newt@uchicago.edu) #(Albert Cahalan,acahalan@cs.uml.edu) # #137 PNG \ r \ n ^ Z \ n [4字节长度] HEAD [HEAD data] [HEAD crc] ... # 0string\ x89PNG PNG图像数据, > 4属于!0x0d0a1a0a腐败, > 4属于0x0d0a1a0a >> 16属于x%ld x >> 20属于x%ld, >> 24字节x%d位 >> 25字节0灰度, >> 25字节2 \ b /彩色RGB, >> 25字节3色图, >> 25个字节4个灰色+ alpha, >> 25字节6 \ b / color RGBA, #>> 26字节0 deflate / 32K, >> 28字节0非隔行 >> 28字节1隔行 1个stringPNG PNG图像数据,损坏 #GIF 0stringGIF8 GIF图像数据 > 4string7a \ b,版本8%s, > 4string9a \ b,版本8%s, > 6 leshort> 0%hd x > 8 leshort> 0%hd #> 10个字节&0x80颜色映射, #> 10个字节&0x07 = 0x00 2个颜色 #> 10个字节&0x07 = 0x01 4种颜色 #> 10个字节&0x07 = 0x02 8个颜色 #> 10个字节&0x07 = 0x03 16个颜色 #> 10个字节&0x07 = 0x04 32个颜色 #> 10个字节&0x07 = 0x05 64个颜色 #> 10个字节&0x07 = 0x06 128个颜色 #> 10个字节&0x07 = 0x07 256个颜色
祝你好运!
有编程方式来确定图像MIMETYPE。
有类System.Drawing.Imaging.ImageCodecInfo 。
这个类有属性MimeType和FormatID 。 它也有一个方法GetImageEncoders返回所有图像编码器的集合。 创build由格式id索引的MIMEtypes的字典很容易。
类System.Drawing.Image具有属性types为System.Drawing.Imaging.ImageFormat的 RawFormat ,其属性Guid等同于类System.Drawing.Imaging.ImageCodecInfo的属性FormatID ,这是从字典中取得MIMETYPE的关键。
例:
创buildMIMEtypes字典的静态方法
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];
尝试将stream加载到System.IO.BinaryReader中。
然后您将需要参考您需要的每种图像格式的规格,并逐字节地加载标题字节以与规格进行比较。 例如这里是PNG规范
补充:PNG的实际文件结构 。