Déterminer le type de fichier d'une image

Je télécharge des images à partir d'un service qui n'inclut pas toujours un type de contenu et ne fournit pas d'extension pour le fichier que je télécharge (ugh, ne demandez pas).

Quelle est la meilleure façon de déterminer le format d'image dans. NET?

L'application qui lit ces images téléchargées doit avoir une extension de fichier appropriée ou tout l'enfer se déchaîne.

44
demandé sur Eric 2008-09-11 09:50:52

6 réponses

Est probablement plus facile serait d'utiliser l'Image.FromFile () puis utilisez la propriété RawFormat, car elle connaît déjà les bits magiques dans les en-têtes pour les formats les plus courants, comme ceci:

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
52
répondu Vinko Vrsalovic 2008-09-11 06:11:18

Tous les formats d'image définissent leurs octets initiaux à une valeur particulière:

Recherchez" format de fichier jpg " en remplaçant jpg par les autres formats de fichiers que vous devez identifier.

Comme le recommande Garth, il existe une base de données de ces 'nombres magiques' montrant le type de fichier de nombreux fichiers. Si vous devez détecter beaucoup de différents types de fichiers il vaut la peine de regarder à travers elle pour trouver les informations dont vous avez besoin. Si vous avez besoin d'étendre cela pour couvrir de nombreux types de fichiers, regardez la commande file associée qui implémente le moteur pour utiliser correctement la base de données (ce n'est pas trivial pour de nombreux formats de fichiers, et est presque un processus statistique)

-Adam

22
répondu Adam Davis 2008-09-11 06:12:18

Vous pouvez utiliser le code ci-dessous sans référence de système.Dessin et création inutile de l'Image de l'objet. Vous pouvez également utiliser Alex solution même sans flux et référence de 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;
}
20
répondu Ivan Kochurkin 2017-05-23 12:17:19

Adam pointe exactement dans la bonne direction.

Si vous voulez savoir comment détecter presque n'importe quel fichier, regardez la base de données derrière la commande file sur une machine UNIX, Linux ou Mac OS X.

file utilise une base de données de "nombres magiques" - ces octets initiaux répertoriés par Adam-pour détecter le type d'un fichier. {[3] } vous indiquera où trouver la base de données sur votre machine, par exemple /usr/share/file/magic. {[5] } vous indiquera son format .

Vous pouvez soit écrire votre propre code de détection basé sur ce que vous voyez dans la base de données, utilisez des bibliothèques pré-empaquetées (par exemple Python-magic), ou - si vous êtes vraiment aventureux-implémentez une version. net de libmagic. Je n'ai pas pu en trouver un, et j'espère qu'un autre Membre pourra en Signaler un.

Dans le cas où vous n'avez pas une machine UNIX à portée de main, la base de données ressemble à ceci:

# 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

Bonne chance!

8
répondu Garth Kidd 2008-09-11 06:19:53

Il existe un moyen programmatique de déterminer le type MIME de l'image.

Il y a un système de classe .Dessin.L'imagerie.ImageCodecInfo .

Cette classe ont des propriétés type mime et FormatID. En outre, il a une méthode GetImageEncoders qui renvoie la collection de tous les encodeurs d'image. Il est facile de créer un dictionnaire de types mime indexés par ID de format.

Classe Système.Dessin.Image ont la propriété RawFormat de Type Système.Dessin.L'imagerie.ImageFormat, qui ont la propriété Guid, qui est l'équivalent de la propriété FormatID de la classe Système.Dessin.L'imagerie.ImageCodecInfo , et c'est la clé pour prendre MIMETYPE du dictionnaire.

Exemple:

Méthode statique pour créer un dictionnaire de types 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;
}

Utilisation:

Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();

FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid];
3
répondu slobodans 2012-08-21 09:18:22

Essayez de charger le flux dans un System. IO. BinaryReader.

Ensuite, vous devrez vous référer aux spécifications pour chaque format d'image dont vous avez besoin, et charger l'en-tête octet par octet pour comparer avec les spécifications. Par exemple, voici les spécifications PNG

Ajouté: la structure de fichier réelle Pour PNG.

0
répondu Ash 2008-09-11 05:54:37