Bestimmen Sie den Dateityp eines Bildes
-
09-06-2019 - |
Frage
Ich lade einige Bilder von einem Dienst herunter, der nicht immer einen Inhaltstyp enthält und keine Erweiterung für die Datei bereitstellt, die ich herunterlade (pfui, fragen Sie nicht).
Wie lässt sich das Bildformat in .NET am besten ermitteln?
Die Anwendung, die diese heruntergeladenen Bilder liest, muss eine korrekte Dateierweiterung haben, sonst bricht die Hölle los.
Lösung
Ein wahrscheinlich einfacher Ansatz wäre Image.FromFile () zu verwenden und dann die RawFormat Eigenschaft verwenden, da sie bereits über die magischen Bits in dem Header für die gängigsten Formate wissen, wie folgen aus:
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
Andere Tipps
Alle Bildformate setzen ihr anfängliches Bytes auf einen bestimmten Wert:
- JPG: 0xFF 0xD8
- PNG: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- GIF: 'G' 'I' 'F'
Suche nach „jpg-Dateiformat“ ersetzt jpg mit der anderen Dateiformaten Sie müssen identifizieren.
Als Garth empfiehlt, gibt es eine Datenbank solcher ‚magischen Zahlen‘ die zeigt, Dateityp vielen Dateien. Wenn Sie viele verschiedene Dateitypen zu erkennen, haben es lohnt sich durch sie suchen, um die benötigten Informationen zu finden. Wenn Sie brauchen, dies viele, viele Dateitypen abdecken zu erweitern, sehen Sie die zugehörigen Dateibefehl die den Motor implementiert die Datenbank zu verwenden, richtig (es ist nicht trivial für viele Dateiformate und ist fast ein statistischer Prozess)
-Adam
Sie können Code verwenden, unten ohne Bezug von System.Drawing und unnötige Erzeugung von Objektbild. Sie können auch Alex Lösung auch ohne Strom und Referenz von System.IO verwenden.
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 zeigt in genau die richtige Richtung.
Wenn Sie wissen möchten, wie man Sinn fast jede Datei , Blick auf die Datenbank hinter dem file
Befehl auf einem UNIX, Linux oder Mac OS X-Maschine.
file
verwendet eine Datenbank von „magischen Zahlen“ - diesem ersten Bytes Adam aufgelistet - ein Dateityp zu erfassen. man file
werden Ihnen sagen, wo die Datenbank auf Ihrem Computer zu finden, zum Beispiel /usr/share/file/magic
. man magic
werden Ihnen sagen, sein Format .
Sie können entweder schreiben Sie Ihren eigenen Erkennungscode auf, was Sie in der Datenbank zu sehen, verwenden abgepackte Bibliotheken (zB python-magic ), oder - wenn Sie wirklich abenteuerlich - eine .NET-Version von libmagic
implementieren. Ich konnte nicht finden, und hoffen, dass ein anderes Mitglied einer darauf hinweisen kann.
Falls Sie nicht über eine UNIX-Maschine handlich, die Datenbank wie folgt aussieht:
# 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
Viel Glück!
Es ist programmatisch Bild MIMETYPE zu bestimmen.
Es gibt Klasse System.Drawing.Imaging.ImageCodecInfo .
Diese Klasse hat Eigenschaften Mimetype und formatID . es hat auch eine Methode GetImageEncoders , die Sammlung aller Bildgeber liefern. Es ist leicht, Wörterbuch der Mime-Typen durch Format-ID indiziert zu erstellen.
Klasse System.Drawing.Image haben Eigenschaft RawFormat der Typ System.Drawing.Imaging.ImageFormat die Eigenschaft haben, Guid , die von der Eigenschaft entspricht formatID die Klasse System.Drawing.Imaging.ImageCodecInfo , und das ist der Schlüssel MIMETYPE von Wörterbuch zu nehmen.
Beispiel:
Statische Methode Wörterbuch von Mime-Typen erstellen
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;
}
Verwendung:
Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();
FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid];
Versuchen Sie, den Strom in ein System.IO.BinaryReader geladen.
Dann müssen Sie die Spezifikationen für jedes Bildformat Sie benötigen, und laden Sie die Header-Byte für Byte beziehen gegen die Spezifikationen zu vergleichen. Zum Beispiel sind hier die PNG Spezifikationen
hinzugefügt: Die tatsächliche Dateistruktur PNG.