Suchen Sie das Bildformat mithilfe des Bitmap-Objekts in C #

82

Ich lade die Binärbytes der Image-Datei-Festplatte und lade sie in ein Bitmap-Objekt. Wie finde ich den Bildtyp [JPEG, PNG, BMP usw.] aus dem Bitmap-Objekt?

Sieht trivial aus. Aber ich konnte es nicht herausfinden!

Gibt es einen alternativen Ansatz?

Schätzen Sie Ihre Antwort.

AKTUALISIERTE RICHTIGE LÖSUNG:

@CMS: Danke für die richtige Antwort!

Beispielcode, um dies zu erreichen.

using (MemoryStream imageMemStream = new MemoryStream(fileData))
{
    using (Bitmap bitmap = new Bitmap(imageMemStream))
    {
        ImageFormat imageFormat = bitmap.RawFormat;
        if (bitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
            //It's a JPEG;
        else if (bitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
            //It's a PNG;
    }
}
Bleistiftscheibe
quelle
3
Sie können den System.Drawing.ImagingNamespace zu Ihren using-Anweisungen hinzufügen , um die Formatprüfungen weniger ausführlich zu gestalten ...
Christian C. Salvadó
@CMS: Einverstanden! Wollte den vollständigen Namespace für zusätzliche Informationen anzeigen.
Bleistiftscheibe
2
Hmmm ... Ich habe die gleiche Technik ausprobiert, aber sie funktioniert nicht. Ich habe ein PNG geladen und wenn ich seinen RawFormat-Wert mit allen ImageFormat. * -Instanzen vergleiche, stimmt keine davon überein. Der tatsächliche RawFormat-Wert ist {b96b3caf-0728-11d3-9d7b-0000f81ef32e}.
Igor Brejc

Antworten:

105

Wenn Sie das Format eines Bildes kennen möchten, können Sie die Datei mit der Image- Klasse laden und ihre RawFormat- Eigenschaft überprüfen :

using(Image img = Image.FromFile(@"C:\path\to\img.jpg"))
{
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
    {
      // ...
    }
}
Christian C. Salvadó
quelle
29
Hinweis: Es scheint, dass img.RawFormat == ImageFormat.Jpegdies nicht funktioniert. Du musst benutzen img.RawFormat.Equals(ImageFormat.Jpeg).
BlueRaja - Danny Pflughoeft
1
@ BlueRaja, ja, warum ist das so? Überschreiben die meisten .NET-Klassen nicht sowohl die Equals () -Methode als auch den Operator? Oder vielleicht formuliere ich es falsch - verwendet .NET bei Verwendung des Operators == nicht standardmäßig die Methode .Equals ()? Bin ich falsch
Pandincus
Gah! Kein Wunder, dass das nicht funktionierte. Ich nahm an, dass == den Trick gemacht hat. Verdammt! Danke Jungs, hat mir gerade ein bisschen Zeit gespart.
Ubiquitous Che
1
==Verwendet keine Referenzgleichheit, es sei denn, es wird überschrieben oder einer der wenigen integrierten Typen Equals. Neben der Verwendung von Equalssich selbst, können Sie die statische verwenden object.Equals(obj1, obj2)(das nennt Equals) für einfache null Sicherheit.
Tim S.
57

Hier ist meine Erweiterungsmethode. Hoffe das hilft jemandem.

public static System.Drawing.Imaging.ImageFormat GetImageFormat(this System.Drawing.Image img)
    {             
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
            return System.Drawing.Imaging.ImageFormat.Jpeg;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
            return System.Drawing.Imaging.ImageFormat.Bmp;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
            return System.Drawing.Imaging.ImageFormat.Png;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Emf))
            return System.Drawing.Imaging.ImageFormat.Emf;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Exif))
            return System.Drawing.Imaging.ImageFormat.Exif;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
            return System.Drawing.Imaging.ImageFormat.Gif;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
            return System.Drawing.Imaging.ImageFormat.Icon;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
            return System.Drawing.Imaging.ImageFormat.MemoryBmp;
        if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
            return System.Drawing.Imaging.ImageFormat.Tiff;
        else
            return System.Drawing.Imaging.ImageFormat.Wmf;            
    }
Sebacipo
quelle
9
Ich kann nicht glauben, dass das .NET Framework dies nicht eingebaut hat und dass dies der einzige Weg ist. Ich bin tatsächlich unter Schock.
Simonlchilds
17

Hier ist mein Code dafür. Sie müssen zuerst das vollständige Image oder den Header (die ersten 4 Bytes) in ein Byte-Array laden.

public enum ImageFormat
{
    Bmp,
    Jpeg,
    Gif,
    Tiff,
    Png,
    Unknown
}

public static ImageFormat GetImageFormat(byte[] bytes)
{
    // 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

    if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
        return ImageFormat.Bmp;

    if (gif.SequenceEqual(bytes.Take(gif.Length)))
        return ImageFormat.Gif;

    if (png.SequenceEqual(bytes.Take(png.Length)))
        return ImageFormat.Png;

    if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
        return ImageFormat.Tiff;

    if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
        return ImageFormat.Tiff;

    if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
        return ImageFormat.Jpeg;

    if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
        return ImageFormat.Jpeg;

    return ImageFormat.Unknown;
}
Alex
quelle
1
JPEG muss auf {255, 216, 255} überprüft werden. Hier ist info en.wikipedia.org/wiki/JPEG
Mirodil
9

natürlich kannst du. ImageFormatbedeutet nicht viel. ImageCodecInfohat viel mehr Bedeutung.

red_dot.png

red_dot.png

<a href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="red_dot.png" title="red_dot.png"/>
</a>

Code:

using System.Linq;

//...

//get image
var file_bytes = System.Convert.FromBase64String(@"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
var file_stream = new System.IO.MemoryStream(file_bytes);
var file_image = System.Drawing.Image.FromStream(file_stream);

//list image formats
var image_formats = typeof(System.Drawing.Imaging.ImageFormat).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).ToList().ConvertAll(property => property.GetValue(null, null));
System.Diagnostics.Debug.WriteLine(image_formats.Count, "image_formats");
foreach(var image_format in image_formats) {
    System.Diagnostics.Debug.WriteLine(image_format, "image_formats");
}

//get image format
var file_image_format = typeof(System.Drawing.Imaging.ImageFormat).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).ToList().ConvertAll(property => property.GetValue(null, null)).Single(image_format => image_format.Equals(file_image.RawFormat));
System.Diagnostics.Debug.WriteLine(file_image_format, "file_image_format");

//list image codecs
var image_codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList();
System.Diagnostics.Debug.WriteLine(image_codecs.Count, "image_codecs");
foreach(var image_codec in image_codecs) {
    System.Diagnostics.Debug.WriteLine(image_codec.CodecName + ", mime: " + image_codec.MimeType + ", extension: " + @image_codec.FilenameExtension, "image_codecs");
}

//get image codec
var file_image_format_codec = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList().Single(image_codec => image_codec.FormatID == file_image.RawFormat.Guid);
System.Diagnostics.Debug.WriteLine(file_image_format_codec.CodecName + ", mime: " + file_image_format_codec.MimeType + ", extension: " + file_image_format_codec.FilenameExtension, "image_codecs", "file_image_format_type");

Debug-Ausgabe:

image_formats: 10
image_formats: MemoryBMP
image_formats: Bmp
image_formats: Emf
image_formats: Wmf
image_formats: Gif
image_formats: Jpeg
image_formats: Png
image_formats: Tiff
image_formats: Exif
image_formats: Icon
file_image_format: Png
image_codecs: 8
image_codecs: Built-in BMP Codec, mime: image/bmp, extension: *.BMP;*.DIB;*.RLE
image_codecs: Built-in JPEG Codec, mime: image/jpeg, extension: *.JPG;*.JPEG;*.JPE;*.JFIF
image_codecs: Built-in GIF Codec, mime: image/gif, extension: *.GIF
image_codecs: Built-in EMF Codec, mime: image/x-emf, extension: *.EMF
image_codecs: Built-in WMF Codec, mime: image/x-wmf, extension: *.WMF
image_codecs: Built-in TIFF Codec, mime: image/tiff, extension: *.TIF;*.TIFF
image_codecs: Built-in PNG Codec, mime: image/png, extension: *.PNG
image_codecs: Built-in ICO Codec, mime: image/x-icon, extension: *.ICO
Built-in PNG Codec, mime: image/png, extension: *.PNG
Alex
quelle
Gut, Alex zu finden! Das sieht zwar chaotisch aus, aber die Grundlagen werden unten in ein paar saubere Erweiterungsmethoden umgewandelt.
Nicholas Petersen
2

Einfach gesagt, du kannst nicht. Der Grund dafür ist, dass Bitmap eine Art Bild ist, genau wie JPEG, PNG usw. Sobald Sie ein Bild in eine Bitmap laden, wird das Bild im Bitmap-Format angezeigt. Es gibt keine Möglichkeit, eine Bitmap zu betrachten und die ursprüngliche Codierung des Bildes zu verstehen (wenn sie sich sogar von der Bitmap unterscheidet).

JaredPar
quelle
1
Ich denke, in diesem Fall ist Bitmap (verwirrenderweise) der Name einer Klasse in C #. Die Bitmap-Klasse enthält ein Bild, das vermutlich JPG, Giff, BMP usw. enthalten kann. Unter allen anderen Umständen sind Sie absolut korrekt.
DarcyThomas
1

Basierend auf Alex 'Arbeit oben (die ich tatsächlich als Lösung stimme, da es sich um eine Zeile handelt - aber ich kann noch nicht abstimmen, haha), habe ich die folgende Funktion für eine Bildbibliothek entwickelt. Es erfordert 4.0

  Public Enum Formats
    Unknown
    Bmp
    Emf
    Wmf
    Gif
    Jpeg
    Png
    Tiff
    Icon
  End Enum

  Public Shared Function ImageFormat(ByVal Image As System.Drawing.Image) As Formats
    If Not System.Enum.TryParse(Of Formats)(System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList().[Single](Function(ImageCodecInfo) ImageCodecInfo.FormatID = Image.RawFormat.Guid).FormatDescription, True, ImageFormat) Then
      Return Formats.Unknown
    End If
  End Function
toddmo
quelle
1

Um mich nicht mit alten Themen zu befassen, sondern um diese Diskussion abzuschließen, möchte ich meinen Weg zum Abfragen aller Bildformate teilen , die Windows bekannt sind.

using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;

public static class ImageExtentions
{
    public static ImageCodecInfo GetCodecInfo(this System.Drawing.Image img)
    {
        ImageCodecInfo[] decoders = ImageCodecInfo.GetImageDecoders();
        foreach (ImageCodecInfo decoder in decoders)
            if (img.RawFormat.Guid == decoder.FormatID)
                return decoder;
        return null;
    }
}

Jetzt können Sie es wie unten gezeigt als Bilderweiterung verwenden:

public void Test(Image img)
{
    ImageCodecInfo info = img.GetCodecInfo();
    if (info == null)
        Trace.TraceError("Image format is unkown");
    else
        Trace.TraceInformation("Image format is " + info.FormatDescription);
}
Agent CK
quelle
0

Ein paar saubere Erweiterungsmethoden für den Typ, Imageum dies zu bestimmen, basierend auf dem Fund von Alex oben ( ImageCodecInfo.GetImageDecoders()).

Dies ist nach dem ersten Aufruf stark optimiert, da das statische ImageCodecsDictionary im Speicher gespeichert wird (jedoch nur, nachdem es einmal verwendet wurde).

public static class ImageCodecInfoX
{

    private static Dictionary<Guid, ImageCodecInfoFull> _imageCodecsDictionary;

    public static Dictionary<Guid, ImageCodecInfoFull> ImageCodecsDictionary 
    {
        get
        {
            if (_imageCodecsDictionary == null) {
                _imageCodecsDictionary =
                    ImageCodecInfo.GetImageDecoders()
                    .Select(i => {
                        var format = ImageFormats.Unknown;
                        switch (i.FormatDescription.ToLower()) {
                            case "jpeg": format = ImageFormats.Jpeg; break;
                            case "png": format = ImageFormats.Png; break;
                            case "icon": format = ImageFormats.Icon; break;
                            case "gif": format = ImageFormats.Gif; break;
                            case "bmp": format = ImageFormats.Bmp; break;
                            case "tiff": format = ImageFormats.Tiff; break;
                            case "emf": format = ImageFormats.Emf; break;
                            case "wmf": format = ImageFormats.Wmf; break;
                        }
                        return new ImageCodecInfoFull(i) { Format = format };
                    })
                    .ToDictionary(c => c.CodecInfo.FormatID);
            }
            return _imageCodecsDictionary;
        }
    }

    public static ImageCodecInfoFull CodecInfo(this Image image)
    {
        ImageCodecInfoFull codecInfo = null;

        if (!ImageCodecsDictionary.TryGetValue(image.RawFormat.Guid, out codecInfo))
            return null;
        return codecInfo;
    }

    public static ImageFormats Format(this Image image)
    {
        var codec = image.CodecInfo();
        return codec == null ? ImageFormats.Unknown : codec.Format;
    }
}

public enum ImageFormats { Jpeg, Png, Icon, Gif, Bmp, Emf, Wmf, Tiff, Unknown }

/// <summary>
/// Couples ImageCodecInfo with an ImageFormats type.
/// </summary>
public class ImageCodecInfoFull
{
    public ImageCodecInfoFull(ImageCodecInfo codecInfo = null)
    {
        Format = ImageFormats.Unknown;
        CodecInfo = codecInfo;
    }

    public ImageCodecInfo CodecInfo { get; set; }

    public ImageFormats Format { get; set; }

}
Nicholas Petersen
quelle
0

Ein seltsames Problem, mit dem ich konfrontiert war, als ich versuchte, den MIME-Typ mithilfe von imagecodeinfo zu ermitteln. Bei einigen PNG-Dateien waren die Anleitungen nicht genau gleich.

Zuerst habe ich mit dem ImageCodecinfo nachgefragt und wenn der Code das Bildformat nicht findet, habe ich das Bildformat mit der Lösung von Matthias Wuttke verglichen.

Wenn beide oben genannten Lösungen fehlgeschlagen sind, verwenden Sie die Erweiterungsmethode, um den MIME-Dateityp abzurufen.

Wenn sich der MIME-Typ ändert, ändert sich auch die Datei. Wir haben die Prüfsumme der heruntergeladenen Dateien so berechnet, dass sie mit der Prüfsumme der Originaldatei auf dem Server übereinstimmt. Für uns war es daher wichtig, die richtige Datei als Ausgabe zu erhalten.

Samuel Joy
quelle
0

Agent CK , ich mochte Ihre Erweiterungsmethode und fügte eine Zeichenfolgenüberladung hinzu. Außerdem habe ich den Code für Ihre Methode reduziert:

public static class ImageExtentions
{
    public static ImageCodecInfo GetCodecInfo(this Image img) =>
        ImageCodecInfo.GetImageDecoders().FirstOrDefault(decoder => decoder.FormatID == img.RawFormat.Guid);

    // Note: this will throw an exception if "file" is not an Image file
    // quick fix is a try/catch, but there are more sophisticated methods
    public static ImageCodecInfo GetCodecInfo(this string file)
    {
        using (var img = Image.FromFile(file))
            return img.GetCodecInfo();
    }
}

// Usage:
string file = @"C:\MyImage.tif";
string description = $"Image format is {file.GetCodecInfo()?.FormatDescription ?? "unknown"}.";
Console.WriteLine(description);
JohnnyIV
quelle
0

Die einfachste Methode wurde von Cesare Imperiali wie folgt angeboten:

var format = new ImageFormat(Image.FromFile(myFile).RawFormat.Guid);

Das .ToString () für ein .jpg gibt jedoch "[ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]" anstelle von "Jpeg" zurück. Wenn Ihnen das wichtig ist, ist hier meine Lösung:

public static class ImageFilesHelper
{
    public static List<ImageFormat> ImageFormats =>
        typeof(ImageFormat).GetProperties(BindingFlags.Static | BindingFlags.Public)
          .Select(p => (ImageFormat)p.GetValue(null, null)).ToList();

    public static ImageFormat ImageFormatFromRawFormat(ImageFormat raw) =>
        ImageFormats.FirstOrDefault(f => raw.Equals(f)) ?? ImageFormat.Bmp;

}
// usage:
var format = ImageFilesHelper.ImageFormatFromRawFormat(Image.FromFile(myFile).RawFormat);
JohnnyIV
quelle