Определить тип файла изображения
-
09-06-2019 - |
Вопрос
Я загружаю несколько изображений из сервиса, который не всегда включает тип контента и не предоставляет расширение для загружаемого файла (тьфу, не спрашивайте).
Как лучше всего определить формат изображения в .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
- Гифка: «Г» «Я» «Ф»
Найдите «формат файла 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.