【问题标题】:Find image format using Bitmap object in C#在 C# 中使用 Bitmap 对象查找图像格式
【发布时间】:2010-11-26 17:15:19
【问题描述】:

我正在加载图像文件硬盘驱动器的二进制字节并将其加载到位图对象中。如何从 Bitmap 对象中找到图像类型[JPEG、PNG、BMP 等]?

看起来微不足道。但是,想不通!

有其他方法吗?

感谢您的回复。

更新的正确解决方案:

@CMS:感谢您的正确回复!

实现此目的的示例代码。

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

【问题讨论】:

  • 您可以将 System.Drawing.Imaging 命名空间添加到您的 using 指令中,以使格式检查不那么冗长...
  • @CMS:同意!想要显示完整的命名空间以获取更多信息。
  • 嗯...我尝试了相同的技术,但它不起作用。我加载了一个 PNG,当我将它的 RawFormat 值与所有 ImageFormat.* 实例进行比较时,它们都不匹配。实际的 RawFormat 值为 {b96b3caf-0728-11d3-9d7b-0000f81ef32e}。

标签: c# .net image


【解决方案1】:

这是我的代码。您必须先将完整的图像或标题(前 4 个字节)加载到字节数组中。

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

    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;

    return ImageFormat.Unknown;
}

【讨论】:

【解决方案2】:

Cesare Imperiali 提供了最简单的方法:

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

但是,.jpg 的 .ToString() 返回“[ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]”而不是“Jpeg”。如果这对您很重要,这是我的解决方案:

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

【讨论】:

    【解决方案3】:

    Agent CK,我喜欢你的扩展方法并添加了字符串重载,另外我减少了你方法的代码:

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

    【讨论】:

      【解决方案4】:

      不想费心老话题,但为了完成这个讨论,我想分享一下我查询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;
          }
      }
      

      现在您可以将其用作图像扩展,如下所示:

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

      【讨论】:

        【解决方案5】:

        当我尝试使用 imagecodeinfo 获取 mime 类型时遇到了一个奇怪的问题。对于某些 png 文件,guid 并不完全相同...

        首先我检查了 ImageCodecinfo,如果代码没有找到图像格式,那么我使用 Matthias Wuttke 的解决方案比较了图像格式。

        如果上述解决方案都失败了,那么使用扩展方法来获取文件mime类型..

        如果 mime 类型发生变化,那么文件也会发生变化,我们正在计算下载的文件校验和以匹配服务器上原始文件的校验和。所以对我们来说,获取正确的文件作为输出很重要。

        【讨论】:

          【解决方案6】:

          根据上面 Alex 的发现 (ImageCodecInfo.GetImageDecoders()),有几个关于 Image 类型的干净扩展方法来确定这一点。

          这是在第一次调用后高度优化的,因为静态 ImageCodecsDictionary 保存在内存中(但仅在使用一次之后)。

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

          【讨论】:

            【解决方案7】:

            基于上面 Alex 的工作(我实际上投票作为解决方案,因为它是一条线 - 但我还不能投票哈哈),我想出了一个图像库的以下函数。 它需要 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
            

            【讨论】:

              【解决方案8】:

              这是我的扩展方法。希望这对某人有所帮助。

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

              【讨论】:

              • 我不敢相信 .NET 框架没有这个功能,而且这是唯一的方法。我真的很震惊。
              【解决方案9】:

              当然可以。 ImageFormat 意义不大。 ImageCodecInfo 有更多的意义。

              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>
              

              代码:

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

              调试输出:

              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
              

              【讨论】:

              • 很高兴找到亚历克斯!虽然这看起来很混乱,但请参阅下面的几个干净的扩展方法。
              【解决方案10】:

              如果你想知道图像的格式,你可以用Image类加载文件,并检查它的RawFormat属性:

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

              【讨论】:

              • 注意:img.RawFormat == ImageFormat.Jpeg 似乎不起作用。你必须使用img.RawFormat.Equals(ImageFormat.Jpeg)
              • @BlueRaja,是的,这是为什么呢?大多数 .NET 类不会同时覆盖 Equals() 方法和运算符吗?或者,也许我的措辞是错误的——在使用 == 运算符时,.NET 默认不使用 .Equals() 方法吗?我错了吗?
              • 啊!没有wonder不工作。我认为 == 成功了。该死!谢谢大家,刚刚为我节省了很多时间。
              • 除非它被覆盖或者是少数内置类型之一,否则== 使用引用相等,而不是Equals。除了自己使用Equals,您还可以使用静态object.Equals(obj1, obj2)(调用Equals)来实现简单的空安全。
              【解决方案11】:

              简单地说,你不能。原因是 Bitmap 是一种图像类型,与 JPEG、PNG 等相同。将图像加载到位图后,位图格式的图像。没有办法查看位图并理解图像的原始编码(如果它甚至与位图不同)。

              【讨论】:

              • 我认为是这种情况位图(令人困惑)是 C# 中的一个类的名称。 Bitmap 类包含一个图像,大概可以是 jpg、giff、bmp 等。在任何其他情况下,是的,你是绝对正确的。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-21
              • 1970-01-01
              • 2019-05-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多