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.
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
Tous les formats d'image définissent leurs octets initiaux à une valeur particulière:
- JPG: 0xFF 0xD8
- PNG: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- GIF: 'G' 'I' ' F '
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
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;
}
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!
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];
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.