代码之家  ›  专栏  ›  技术社区  ›  Nick Clarke

从字节[]中查找图像的内容类型

  •  8
  • Nick Clarke  · 技术社区  · 17 年前

    目前,我有一个数据库列,它只存储字节[],我用它在网页上显示图像。

    MemoryStream ms = new MemoryStream(imageBytes);
    Image image = Image.FromStream(ms);
    image.Save(context.HttpContext.Response.OutputStream, <--ContentType-->);
    

    当然,我可以将ContentType保存在表中的另一列中,但我只是想知道是否有其他方法,例如,也许.Net有办法查询数据以获取类型。

    6 回复  |  直到 17 年前
        1
  •  16
  •   vit    17 年前
        2
  •  14
  •   Community Mohan Dere    9 年前

    裁判: Stackoverflow - Getting image dimensions without reading the entire file

    ImageFormat contentType = ImageHelper.GetContentType(this.imageBytes);
    
    MemoryStream ms = new MemoryStream(this.imageBytes);
    Image image = Image.FromStream(ms);
    image.Save(context.HttpContext.Response.OutputStream, contentType);
    

    然后是helper类:

    public static class ImageHelper
    {
        public static ImageFormat GetContentType(byte[] imageBytes)
        {
            MemoryStream ms = new MemoryStream(imageBytes);
    
            using (BinaryReader br = new BinaryReader(ms))
            {
                int maxMagicBytesLength = imageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
    
                byte[] magicBytes = new byte[maxMagicBytesLength];
    
                for (int i = 0; i < maxMagicBytesLength; i += 1)
                {
                    magicBytes[i] = br.ReadByte();
    
                    foreach (var kvPair in imageFormatDecoders)
                    {
                        if (magicBytes.StartsWith(kvPair.Key))
                        {
                            return kvPair.Value;
                        }
                    }
                }
    
                throw new ArgumentException("Could not recognise image format", "binaryReader");
            }
        }
    
        private static bool StartsWith(this byte[] thisBytes, byte[] thatBytes)
        {
            for (int i = 0; i < thatBytes.Length; i += 1)
            {
                if (thisBytes[i] != thatBytes[i])
                {
                    return false;
                }
            }
            return true;
        }
    
        private static Dictionary<byte[], ImageFormat> imageFormatDecoders = new Dictionary<byte[], ImageFormat>()
        {
            { new byte[]{ 0x42, 0x4D }, ImageFormat.Bmp},
            { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, ImageFormat.Gif },
            { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, ImageFormat.Gif },
            { new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, ImageFormat.Png },
            { new byte[]{ 0xff, 0xd8 }, ImageFormat.Jpeg },
        };
    
        3
  •  8
  •   Joost Aarts    14 年前

    这对我很有效, ms 成为记忆之流。缺点是它必须加载映像。

    Dim fmt As System.Drawing.Imaging.ImageFormat
    Dim content As String
    
    Using bmp As New Drawing.Bitmap(ms)
        fmt = bmp.RawFormat
    End Using
    
    Select Case fmt.Guid
        Case Drawing.Imaging.ImageFormat.Bmp.Guid
            content = "image/x-ms-bmp"
    
        Case Drawing.Imaging.ImageFormat.Jpeg.Guid
            content = "image/jpeg"
    
        Case Drawing.Imaging.ImageFormat.Gif.Guid
            content = "image/gif"
    
        Case Drawing.Imaging.ImageFormat.Png.Guid
            content = "image/png"
    
        Case Else
            content = "application/octet-stream"
    
    End Select
    
        4
  •  3
  •   Alexander Derck    10 年前

    使用Linq稍微重写Nick Clarke的方法:

    public class Program
    {
       public static void Main(string[] args)
       {
          byte[] byteArray = File.ReadAllBytes(@"C:/users/Alexander/image.jpg");
          ImagePartType type = byteArray.GetImageType();
       }
    }
    
    
    public static class ImageHelper
    {
        public static ImagePartType GetImageType(this byte[] imageBytes)
        {
            foreach(var imageType in imageFormatDecoders)
            {
                if (imageType.Key.SequenceEqual(imageBytes.Take(imageType.Key.Length)))
                    return imageType.Value;
            }
    
            throw new ArgumentException("Imagetype is unknown!");
        }
    
        private static Dictionary<byte[], ImagePartType> imageFormatDecoders 
                         = new Dictionary<byte[], ImagePartType>()
        {
           { new byte[]{ 0x42, 0x4D }, ImagePartType.Bmp},
           { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, ImagePartType.Gif },
           { new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, ImagePartType.Gif },
           { new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, ImagePartType.Png },
           { new byte[]{ 0xff, 0xd8 }, ImagePartType.Jpeg }
        };
    }
    

    我曾经 ImagePartType 因为我目前正在使用OpenXMLSDK,但只需更改字典中的类型:)

        5
  •  1
  •   Darin Dimitrov    17 年前

    没有从内置的.NET流中检测内容类型的标准方法。您可以实现自己的算法,在某些情况下可以实现这一点 well-known

        6
  •  0
  •   Jon Skeet    17 年前

    是吗 RawFormat 物业部为你工作?

    MemoryStream ms = new MemoryStream(imageBytes);
    Image image = Image.FromStream(ms);
    image.Save(context.HttpContext.Response.OutputStream, image.RawFormat);
    
    推荐文章