当前位置:  开发笔记 > 编程语言 > 正文

确定文件是否是图像

如何解决《确定文件是否是图像》经验,为你挑选了8个好方法。

我循环遍历目录并复制所有文件.现在我做string.EndsWith检查".jpg"".png"等..

有没有更优雅的方法来确定文件是否是一个图像(任何图像类型)没有上面的hacky检查?



1> Mitch Wheat..:

检查文件是否有已知标头.(链接中的信息也在这个答案中提到)

PNG文件的前八个字节始终包含以下(十进制)值:137 80 78 71 13 10 26 10


抱歉,您的链接不再有效.我有403错误.
是的链接已死:(
最初发布于2008年7月的链接内容存档于[WayBackMachine](http://web.archive.org/web/20090302032444/http://www.mikekunz.com/image_file_header.html)

2> bendewey..:

查看System.IO.Path.GetExtension

这是一个快速的样本.

public static readonly List ImageExtensions = new List { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG" };

private void button_Click(object sender, RoutedEventArgs e)
{
    var folder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    var files = Directory.GetFiles(folder);
    foreach(var f in files)
    {
        if (ImageExtensions.Contains(Path.GetExtension(f).ToUpperInvariant()))
        {
            // process image
        }
    }
}


是的,但它仍然是一个字符串比较.如果我将.jpf文件重命名为.txt怎么办?

3> Aydin..:

这将查看文件的前几个字节并确定它是否是图像.

using System.Collections.Generic;
using System.IO;
using System.Linq;

public static class Extension
{
    public static bool IsImage(this Stream stream)
    {
        stream.Seek(0, SeekOrigin.Begin);

        List jpg = new List { "FF", "D8" };
        List bmp = new List { "42", "4D" };
        List gif = new List { "47", "49", "46" };
        List png = new List { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
        List> imgTypes = new List> { jpg, bmp, gif, png };

        List bytesIterated = new List();

        for (int i = 0; i < 8; i++)
        {
            string bit = stream.ReadByte().ToString("X2");
            bytesIterated.Add(bit);

            bool isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
            if (isImage)
            {
                return true;
            }
        }

        return false;
    }
}

编辑

我对上面的内容进行了一些更改,以便您可以根据需要添加自己的图像,还可以删除不必要的集合.我还添加了一个接受out类型参数的重载string,将值设置为流组成的图像类型.

public static class Extension
{
    static Extension()
    {
        ImageTypes = new Dictionary();
        ImageTypes.Add("FFD8","jpg");
        ImageTypes.Add("424D","bmp");
        ImageTypes.Add("474946","gif");
        ImageTypes.Add("89504E470D0A1A0A","png");
    }

    /// 
    ///      Registers a hexadecimal value used for a given image type 
    ///      The type of image, example: "png" 
    ///      The type of image, example: "89504E470D0A1A0A" 
    /// 
    public static void RegisterImageHeaderSignature(string imageType, string uniqueHeaderAsHex)
    {
        Regex validator = new Regex(@"^[A-F0-9]+$", RegexOptions.CultureInvariant);

        uniqueHeaderAsHex = uniqueHeaderAsHex.Replace(" ", "");

        if (string.IsNullOrWhiteSpace(imageType))         throw new ArgumentNullException("imageType");
        if (string.IsNullOrWhiteSpace(uniqueHeaderAsHex)) throw new ArgumentNullException("uniqueHeaderAsHex");
        if (uniqueHeaderAsHex.Length % 2 != 0)            throw new ArgumentException    ("Hexadecimal value is invalid");
        if (!validator.IsMatch(uniqueHeaderAsHex))        throw new ArgumentException    ("Hexadecimal value is invalid");

        ImageTypes.Add(uniqueHeaderAsHex, imageType);
    }

    private static Dictionary ImageTypes;

    public static bool IsImage(this Stream stream)
    {
        string imageType;
        return stream.IsImage(out imageType);
    }

    public static bool IsImage(this Stream stream, out string imageType)
    {
        stream.Seek(0, SeekOrigin.Begin);
        StringBuilder builder = new StringBuilder();
        int largestByteHeader = ImageTypes.Max(img => img.Value.Length);

        for (int i = 0; i < largestByteHeader; i++)
        {
            string bit = stream.ReadByte().ToString("X2");
            builder.Append(bit);

            string builtHex = builder.ToString();
            bool isImage = ImageTypes.Keys.Any(img => img == builtHex);
            if (isImage)
            {
                imageType = ImageTypes[builder.ToString()];
                return true;
            }
        }
        imageType = null;
        return false;
    }
}


一些错别字:应该返回IsImage(stream,out imageType); 而不是返回stream.IsImage(out imageType); 应该是int largestByteHeader = ImageTypes.Max(img => img.Key.Length)而不是int largestByteHeader = ImageTypes.Max(img => img.Value.Length)
不实用,因为你缺少很多可能的图像类型.
实现你刚刚编写的内容,看看它是否编译

4> Jeremy Cook..:
System.Web.MimeMapping.GetMimeMapping(filename).StartsWith("image/");

MimeMapping.GetMimeMapping 产生这些结果:

file.jpg:image/jpeg

file.gif:image/gif

file.jpeg:image/jpeg

file.png:image/png

file.bmp:image/bmp

file.tiff:image/tiff

file.svg:application/octet-stream

在大多数情况下,file.svg不返回图像/ MIME类型,因为您可能不会像处理标量图像那样处理矢量图像.检查MIME类型时,请注意SVG确实具有标准MIME类型image/svg + xml,即使GetMimeMapping它没有返回它.


如果有意更改文件扩展名,例如从.jpg到.txt,则会失败,即System.Web.MimeMapping.GetMimeMapping(filename)的输出将为text/plain

5> yogihosting..:

我们可以使用命名空间System.Drawing中的图像和图形类; 做我们的工作.如果代码无错误地运行,则它是图像,否则不是.这就是让DotNet框架为我们工作.代码 -

public string CheckFile(file)
{
    string result="";
    try
    {
        System.Drawing.Image imgInput = System.Drawing.Image.FromFile(file);
        System.Drawing.Graphics gInput = System.Drawing.Graphics.fromimage(imgInput);  
        Imaging.ImageFormat thisFormat = imgInput.RawFormat;   
        result="It is image";        
    }
    catch(Exception ex)
    {
        result="It is not image"; 
    }
    return result;
}



6> 小智..:

如果您想要一种快速的方法来在完全从文件中读取图像文件之前对其进行验证,除了比较文件扩展名之外,您还可以检查其标题以查找文件签名(以下代码IsValidImageFile()检查BMP,GIF87a,GIF89a,PNG, TIFF,JPEG

    /// 
    /// Reads the header of different image formats
    /// 
    /// Image file
    /// true if valid file signature (magic number/header marker) is found
    private bool IsValidImageFile(string file)
    {
        byte[] buffer = new byte[8];
        byte[] bufferEnd = new byte[2];

        var bmp = new byte[] { 0x42, 0x4D };               // BMP "BM"
        var gif87a = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 };     // "GIF87a"
        var gif89a = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };     // "GIF89a"
        var png = new byte[] { 0x89, 0x50, 0x4e, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };   // PNG "\x89PNG\x0D\0xA\0x1A\0x0A"
        var tiffI = new byte[] { 0x49, 0x49, 0x2A, 0x00 }; // TIFF II "II\x2A\x00"
        var tiffM = new byte[] { 0x4D, 0x4D, 0x00, 0x2A }; // TIFF MM "MM\x00\x2A"
        var jpeg = new byte[] { 0xFF, 0xD8, 0xFF };        // JPEG JFIF (SOI "\xFF\xD8" and half next marker xFF)
        var jpegEnd = new byte[] { 0xFF, 0xD9 };           // JPEG EOI "\xFF\xD9"

        try
        {
            using (System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                if (fs.Length > buffer.Length)
                {
                    fs.Read(buffer, 0, buffer.Length);
                    fs.Position = (int)fs.Length - bufferEnd.Length;
                    fs.Read(bufferEnd, 0, bufferEnd.Length);
                }

                fs.Close();
            }

            if (this.ByteArrayStartsWith(buffer, bmp) ||
                this.ByteArrayStartsWith(buffer, gif87a) ||
                this.ByteArrayStartsWith(buffer, gif89a) ||
                this.ByteArrayStartsWith(buffer, png) ||
                this.ByteArrayStartsWith(buffer, tiffI) ||
                this.ByteArrayStartsWith(buffer, tiffM))
            {
                return true;
            }

            if (this.ByteArrayStartsWith(buffer, jpeg))
            {
                // Offset 0 (Two Bytes): JPEG SOI marker (FFD8 hex)
                // Offest 1 (Two Bytes): Application segment (FF?? normally ??=E0)
                // Trailer (Last Two Bytes): EOI marker FFD9 hex
                if (this.ByteArrayStartsWith(bufferEnd, jpegEnd))
                {
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, Lang.Lang.ErrorTitle + " IsValidImageFile()", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        return false;
    }

    /// 
    /// Returns a value indicating whether a specified subarray occurs within array
    /// 
    /// Main array
    /// Subarray to seek within main array
    /// true if a array starts with b subarray or if b is empty; otherwise false
    private bool ByteArrayStartsWith(byte[] a, byte[] b)
    {
        if (a.Length < b.Length)
        {
            return false;
        }

        for (int i = 0; i < b.Length; i++)
        {
            if (a[i] != b[i])
            {
                return false;
            }
        }

        return true;
    }

检查标头签名可能很快,因为它不会加载整个文件或创建大对象,特别是在处理多个文件时。但是它不会检查其余数据是否格式正确。为此,可以尝试将文件加载到Image对象的第二步(这样可以确定文件可以由程序显示和处理)。

bool IsValidImage(string filename)
{
    try
    {
        using(Image newImage = Image.FromFile(filename))
        {}
    }
    catch (OutOfMemoryException ex)
    {
        //The file does not have a valid image format.
        //-or- GDI+ does not support the pixel format of the file

        return false;
    }
    return true;
}



7> 小智..:

我使用以下方法。它使用内置的图像解码器检索系统识别为图像文件的扩展名列表,然后将这些扩展名与您传入的文件名的扩展名进行比较。返回简单的TRUE / FALSE。

public static bool IsRecognisedImageFile(string fileName)
{
    string targetExtension = System.IO.Path.GetExtension(fileName);
    if (String.IsNullOrEmpty(targetExtension))
        return false;
    else
        targetExtension = "*" + targetExtension.ToLowerInvariant();

    List recognisedImageExtensions = new List();

    foreach (System.Drawing.Imaging.ImageCodecInfo imageCodec in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders())
        recognisedImageExtensions.AddRange(imageCodec.FilenameExtension.ToLowerInvariant().Split(";".ToCharArray()));

    foreach (string extension in recognisedImageExtensions)
    {
        if (extension.Equals(targetExtension))
        {
            return true;
        }
    }
    return false;
}



8> shahkalpesh..:

看看这是否有帮助.

编辑:此外,Image.FromFile(....).RawFormat可能会有所帮助.如果文件不是图像,它可能会抛出异常.

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有