我正在从服务中下载一些图像,这些服务并不总是包含内容类型,并且不提供我正在下载的文件的扩展名(哦,不要问)。
确定.NET中图像格式的最佳方法是什么?
正在读取这些下载的图像的应用程序需要具有适当的文件扩展名,否则所有地狱都可能会崩溃。
一种可能更简单的方法是使用Image.FromFile()然后使用RawFormat属性,因为它已经知道最常见格式的标头中的魔术位,如下所示:
1 2 3 4 5 6
| 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 |
您可以在不参考System.Drawing以及不必要创建对象Image的情况下使用以下代码。同样,即使没有流和System.IO的引用,您也可以使用Alex解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public enum ImageFormat
{
bmp,
jpeg,
gif,
tiff,
png,
unknown
}
public static ImageFormat GetImageFormat(Stream stream)
{
// see /d/jc/2023041422/mmgbasiic4o34.bmp;
if (gif.SequenceEqual(buffer.Take(gif.Length)))
return ImageFormat.webp;
if (png.SequenceEqual(buffer.Take(png.Length)))
return ImageFormat.webp;
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.webp;
if (jpeg2.SequenceEqual(buffer.Take(jpeg2.Length)))
return ImageFormat.webp;
return ImageFormat.unknown;
} |
所有图像格式均将其初始字节设置为特定值:
-
JPG:0xFF 0xD8
-
PNG:0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
-
GIF:" G"" I"" F"
搜索" jpg文件格式",将jpg替换为您需要识别的其他文件格式。
正如Garth建议的那样,有一个数据库可以显示许多文件的文件类型。如果您必须检测许多不同的文件类型,则值得一看以查找所需的信息。如果确实需要扩展它以涵盖许多文件类型,请查看相关的文件命令,该命令实现了引擎以正确使用数据库(对于许多文件格式而言,这并非易事,并且几乎是一个统计过程)
-亚当
亚当指的是正确的方向。
如果要查找几乎所有文件的方法,请查看UNIX,Linux或Mac OS X计算机上file命令后面的数据库。
file使用"魔数"数据库(Adam列出的那些初始字节)来检测文件的类型。 man file会告诉您如何在计算机上找到数据库,例如/usr/share/file/magic。 man magic会告诉您其格式。
您可以根据在数据库中看到的内容编写自己的检测代码,也可以使用预打包的库(例如python-magic),也可以(如果确实喜欢冒险的话)实施libmagic的.NET版本。我找不到一个,希望另一个成员可以指出一个。
如果您没有方便的UNIX计算机,则数据库如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| # 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
^Z
[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的方法。
有类System.Drawing.Imaging.ImageCodecInfo。
此类具有MimeType和FormatID属性。它还有一个GetImageEncoders方法,该方法返回所有图像编码器的集合。
创建由格式ID索引的mime类型字典很容易。
System.Drawing.Image类具有类型为System.Drawing.Imaging.ImageFormat的RawFormat属性,其属性Guid等同于System.Drawing.Imaging.ImageCodecInfo类的属性FormatID,这是从字典中获取MIMETYPE的关键。
例:
创建mime类型字典的静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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;
} |
采用:
1 2 3 4 5
| Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();
FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid]; |
尝试将流加载到System.IO.BinaryReader中。
然后,您需要参考所需的每种图像格式的规范,并逐字节加载标头以与规范进行比较。例如,这是PNG规范
补充:PNG的实际文件结构。