Вопрос

Я загружаю несколько изображений из сервиса, который не всегда включает тип контента и не предоставляет расширение для загружаемого файла (тьфу, не спрашивайте).

Как лучше всего определить формат изображения в .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 другими форматами файлов, которые вам нужно идентифицировать.

Как рекомендует Гарт, существует база данных таких «магических чисел» показывая тип файла многих файлов.Если вам нужно обнаружить множество разных типов файлов, стоит просмотреть его, чтобы найти нужную информацию.Если вам нужно расширить это, чтобы охватить множество типов файлов, посмотрите соответствующие команда файла который реализует движок для правильного использования базы данных (это нетривиально для многих форматов файлов и представляет собой почти статистический процесс)

-Адам

Вы можете использовать приведенный ниже код без ссылки на 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 изображения.

есть класс System.Drawing.Imaging.ImageCodecInfo.

У этого класса есть свойства Миметип и идентификатор формата.Также у него есть метод GetImageEncoders которые возвращают коллекцию всех кодировщиков изображений.Легко создать словарь типов mime, индексированных по идентификатору формата.

Сорт System.Drawing.Image иметь собственность RawFormat типа System.Drawing.Imaging.ImageFormat которые имеют собственность Руководство что эквивалентно свойству идентификатор формата класса System.Drawing.Imaging.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

Добавлен:Настоящий файловая структура для PNG.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top