Encuentre el formato de imagen usando el objeto Bitmap en C #

83

Estoy cargando los bytes binarios del disco duro del archivo de imagen y lo estoy cargando en un objeto Bitmap. ¿Cómo encuentro el tipo de imagen [JPEG, PNG, BMP, etc.] del objeto de mapa de bits?

Parece trivial. ¡Pero no pude entenderlo!

¿Existe un enfoque alternativo?

Agradezco tu respuesta.

SOLUCIÓN CORRECTA ACTUALIZADA:

@CMS: ¡Gracias por la respuesta correcta!

Código de muestra para lograr esto.

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;
    }
}
lapiz pizarra
fuente
3
Puede agregar el System.Drawing.Imagingespacio de nombres a sus directivas using, para que las comprobaciones de formato sean menos detalladas ...
Christian C. Salvadó
@CMS: ¡De acuerdo! Quería mostrar el espacio de nombres completo para obtener información adicional.
pencilslate
2
Hmmm ... Probé la misma técnica, pero no funciona. Tengo un PNG cargado y cuando comparo su valor RawFormat con todas las instancias de ImageFormat. *, Ninguna de ellas coincide. El valor real de RawFormat es {b96b3caf-0728-11d3-9d7b-0000f81ef32e}.
Igor Brejc

Respuestas:

106

Si desea conocer el formato de una imagen, puede cargar el archivo con la clase Image y verificar su propiedad RawFormat :

using(Image img = Image.FromFile(@"C:\path\to\img.jpg"))
{
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
    {
      // ...
    }
}
Christian C. Salvadó
fuente
29
Nota: parece que img.RawFormat == ImageFormat.Jpegno funciona. Usted tiene que utilizar img.RawFormat.Equals(ImageFormat.Jpeg).
BlueRaja - Danny Pflughoeft
1
@BlueRaja, sí, ¿por qué? ¿No anulan la mayoría de las clases .NET tanto el método Equals () como el operador? O, tal vez lo estoy expresando mal: ¿.NET no usa el método .Equals () de forma predeterminada cuando usa el operador ==? ¿Me equivoco?
Pandincus
¡Gah! No es de extrañar que eso no estuviera funcionando. Supuse que == hizo el truco. ¡Maldición! Gracias chicos, me ahorró un montón de tiempo ahora.
Che ubicuo
1
A menos que esté anulado o sea uno de los pocos tipos integrados, ==usa igualdad de referencia, no Equals. Además de usarte a Equalsti mismo, puedes usar el static object.Equals(obj1, obj2)(que llama Equals) para una seguridad nula simple.
Tim S.
58

Aquí está mi método de extensión. Espero que esto ayude a alguien.

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
fuente
9
No puedo creer que el marco .NET no tenga esto integrado y que esta sea la única forma. De hecho, estoy en shock.
simonlchilds
18

aquí está mi código para esto. Primero debe cargar la imagen completa o el encabezado (primeros 4 bytes) en una matriz de bytes.

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
fuente
1
JPEG debe comprobarse para {255, 216, 255}. Aquí hay información en.wikipedia.org/wiki/JPEG
Mirodil
9

por supuesto que puede. ImageFormatno significa mucho. ImageCodecInfotiene mucho más significado.

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>

código:

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

salida de depuración:

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
fuente
¡Bien, encuentra a Alex! Aunque esto parece complicado, vea los conceptos básicos convertidos en un par de métodos de extensión limpios a continuación.
Nicholas Petersen
2

Simplemente hablando, no puedes. La razón es que Bitmap es un tipo de imagen de la misma manera que lo son JPEG, PNG, etc. Una vez que carga una imagen en un mapa de bits, la imagen del formato de mapa de bits. No hay forma de ver un mapa de bits y comprender la codificación original de la imagen (si es que es incluso diferente al mapa de bits).

JaredPar
fuente
1
Creo que en este caso Bitmap (confusamente) es el nombre de una clase en C #. La clase Bitmap contiene una imagen, que presumiblemente puede jpg, giff, bmp, etc. En cualquier otra circunstancia, sí, tienes toda la razón.
DarcyThomas
2

Para no molestarme en el tema anterior, pero para completar esta discusión, quiero compartir mi forma de consultar todos los formatos de imagen, conocidos por 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;
    }
}

Ahora puede usarlo como una extensión de imagen como se muestra a continuación:

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);
}
Agente CK
fuente
1

Basado en el trabajo de Alex anterior (que en realidad voto como la solución, ya que es una línea, pero todavía no puedo votar jaja), se me ocurrió la siguiente función para una biblioteca de imágenes. Requiere 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
fuente
0

Un par de métodos de extensión limpios en el tipo Imagepara determinar esto, basados ​​en el hallazgo de Alex arriba ( ImageCodecInfo.GetImageDecoders()).

Esto está altamente optimizado después de la primera llamada, ya que el ImageCodecsDictionary estático se guarda en la memoria (pero solo después de que se haya usado una vez).

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

un problema extraño que enfrenté cuando intentaba obtener el tipo mime usando imagecodeinfo ... para algunos archivos png, los guids no eran exactamente iguales ...

Primero estaba verificando con ImageCodecinfo y si el código no encuentra el formato de imagen, luego comparé el formato de imagen usando la solución de Matthias Wuttke.

si ambas soluciones mencionadas anteriormente fallaron, entonces use el método de extensión para obtener el tipo de archivo mime.

si el tipo de mime cambia, entonces el archivo también cambia, estábamos calculando la suma de verificación de los archivos descargados para que coincida con la suma de verificación del archivo original en el servidor ... así que para nosotros era importante obtener el archivo adecuado como salida.

Samuel Joy
fuente
0

Agente CK , me gustó su método de extensión y agregué una sobrecarga de cadenas, además reduje el código para su método:

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

Cesare Imperiali ofreció el método más simple de la siguiente manera:

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

Sin embargo, .ToString () para un .jpg devuelve "[ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]" en lugar de "Jpeg". Si eso te importa, aquí está mi solución:

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
fuente