2009-09-09 9 views
74

Załaduję binarne bajty dysku twardego pliku obrazu i ładuję go do obiektu Bitmap. Jak znaleźć typ obrazu [JPEG, PNG, BMP itd.] Z obiektu Bitmap?Znajdź format obrazu za pomocą obiektu Bitmap w C#

Wygląda banalnie. Ale nie mogłem tego rozgryźć!

Czy istnieje alternatywne podejście?

Doceń swoją odpowiedź.

AKTUALIZACJA poprawne rozwiązanie:

@CMS: Dzięki za prawidłowe odpowiedzi!

Przykładowy kod, aby to osiągnąć.

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; 
    } 
} 
+3

Można dodać 'nazw System.Drawing.Imaging' do korzystających z dyrektyw, w celu dokonania kontroli formatu mniej verbose ... – CMS

+0

@CMS: Zgoda! Chciał wyświetlić pełną przestrzeń nazw, aby uzyskać dodatkowe informacje. – pencilslate

+1

Hmmm ... Próbowałem tej samej techniki, ale to nie działa. Mam załadowany PNG i kiedy porównam jego wartość RawFormat do wszystkich instancji ImageFormat. *, Żadna z nich nie pasuje. Rzeczywista wartość formatu RawFormat to {b96b3caf-0728-11d3-9d7b-0000f81ef32e}. –

Odpowiedz

93

Jeśli chcesz wiedzieć, format obrazu, można załadować plik z klasą Image i sprawdzić jego RawFormat właściwość:

using(Image img = Image.FromFile(@"C:\path\to\img.jpg")) 
{ 
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg)) 
    { 
     // ... 
    } 
} 
+26

Uwaga: Wygląda na to, że 'img.RawFormat == ImageFormat.Jpeg' nie działa. * Masz * używać 'img.RawFormat.Equals (ImageFormat.Jpeg)'. –

+0

@ BlueRaja, tak, dlaczego tak jest? Czy większość klas .NET nie zastępuje metody Equals() i operatora? Lub, być może I'm phrasing to źle - nie. NET używać metody .Equals() domyślnie podczas korzystania z operatora ==? Czy jestem niepoprawny? – Pandincus

+0

Gah! No * wonder *, który nie działał. Założę się, że == zrobił lewę. Cholerny! Dzięki chłopaki, uratowaliście mi teraz trochę czasu. –

2

Po prostu nie można. Powodem, dla którego ta mapa bitowa jest rodzajem obrazu w taki sam sposób, jak JPEG, PNG, itp. Po załadowaniu obrazu do bitmapy obraz mapy bitowej. Nie ma sposobu, aby spojrzeć na bitmapę i zrozumieć oryginalne kodowanie obrazu (jeśli jest nawet inny niż Bitmapa).

+0

Myślę, że w tym przypadku bitmap (myląco) to nazwa klasy w języku C#. Klasa Bitmap zawiera obraz, który prawdopodobnie może być jpg, giff, bmp itd. W innych okolicznościach tak, masz całkowitą rację. – DarcyThomas

5

Oczywiście można. ImageFormat nie znaczy wiele. ImageCodecInfo ma dużo więcej znaczenia.

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> 

kod: Wyjście

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:

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 
+0

Dobra znajo Alex! Choć wygląda to niechlujnie, ale zobacz podstawy obrócone w kilka czystych metod rozszerzenia poniżej. –

41

Oto moja metoda rozszerzenie. Mam nadzieję, że to pomoże komuś.

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;    
    } 
+2

Nie mogę uwierzyć, że środowisko .NET nie ma tego zapakowanego i że jest to jedyny sposób. Jestem w szoku. – simonlchilds

1

podstawie prac Alexa powyżej (które faktycznie głosować jako rozwiązanie, gdyż jest to jedna linia - ale nie mogę jeszcze głosować haha), wymyśliłem następującą funkcją biblioteki obrazów. Wymaga 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 
11

Oto mój kod dla tego. Musisz najpierw załadować pełny obraz lub nagłówek (pierwsze 4 bajty) do tablicy bajtów.

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; 
} 
+1

Plik JPEG musi być sprawdzany przez {255, 216, 255}. Oto informacje http://en.wikipedia.org/wiki/JPEG – Mirodil

0

Kilka czystych metod rozszerzenie na typ Image do określania tego, w oparciu o znaleziska Alex powyżej (ImageCodecInfo.GetImageDecoders()).

Jest to wysoce zoptymalizowane po pierwszym wywołaniu, ponieważ statyczny ImageCodecsDictionary jest zapisywany w pamięci (ale tylko po tym, jak został użyty raz).

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; } 

} 
0

jeden dziwny problem mam do czynienia, gdy starałem się uzyskać typu MIME używając imagecodeinfo .. dla niektórych png Files GUID nie były dokładnie takie same ...

pierwszy Sprawdzałem z ImageCodecinfo i jeśli kod nie znajdzie formatu obrazu, to porównałem format obrazu używając rozwiązania Matthiasa Wuttkego.

gdy oba powyższe rozwiązanie nie powiodła następnie wykorzystał metodę rozszerzenia aby uzyskać typ MIME pliku ..

przypadku zmiany typu MIME to plik zmienia się także, byliśmy obliczania sumy kontrolnej pobranych plików pasujące do z suma kontrolna oryginalnego pliku na serwerze ... więc dla nas było ważne, aby uzyskać właściwy plik jako wynik.

0

Nie przejmuj się starym tematem, ale aby dokończyć tę dyskusję, chcę podzielić się moją opinią na temat formatów obrazów wszystkich, znanych z systemu Windows.

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; 
    } 
} 

Teraz można go używać jako przedłużenie obrazu, jak pokazano poniżej:

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); 
}