Выяснение ContentType изображения из байта [] - PullRequest
8 голосов
/ 07 августа 2009

Есть ли способ узнать, какой ContentType изображения имеет только исходные байты?

На данный момент у меня есть столбец базы данных, в котором хранится только байт [], который я использую для отображения изображения на веб-странице.

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

Конечно, я мог бы просто сохранить ContentType в другом столбце таблицы, но просто подумал, есть ли другой способ, например, может быть, в .Net есть способ опросить данные, чтобы получить тип.

Ответы [ 6 ]

15 голосов
/ 07 августа 2009

Ознакомьтесь с этой таблицей подписей файлов .

14 голосов
/ 07 августа 2009

Файловые / магические подписи - вот путь. Ниже приведена рабочая версия кода.

Ссылка: Stackoverflow - получение размеров изображения без чтения всего файла

ImageFormat contentType = ImageHelper.GetContentType(this.imageBytes);

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

А потом вспомогательный класс:

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 },
    };
6 голосов
/ 09 января 2012

Это сработало для меня, 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
2 голосов
/ 08 января 2016

Немного переписал метод Ника Кларка, используя Linq:

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, потому что я сейчас работаю с Open XML SDK, но просто измените тип в словаре:)

1 голос
/ 07 августа 2009

Не существует стандартного способа определения типа контента из встроенного в .NET потока. Вы могли бы реализовать свой собственный алгоритм, который мог бы достичь этого для некоторых известных графических форматов, считав первые несколько байтов и попытавшись соответствовать формату.

0 голосов
/ 07 августа 2009

Работает ли свойство RawFormat для вас?

MemoryStream ms = new MemoryStream(imageBytes);
Image image = Image.FromStream(ms);
image.Save(context.HttpContext.Response.OutputStream, image.RawFormat);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...