我正在从一个服务下载一些图像,该服务并不总是包含内容类型,并且不提供我正在下载的文件的扩展名(呃,不要问)。

确定 .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 文件格式”,将 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];

尝试将流加载到 System.IO.BinaryReader 中。

然后,您需要参考所需的每种图像格式的规范,并逐字节加载标头以与规范进行比较。例如,这里是 PNG规格

添加:实际上 文件结构 对于巴布亚新几内亚。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top