36

使用 C# 如何测试文件是否为 jpeg?我应该检查 .jpg 扩展名吗?

谢谢

4

16 回答 16

108

几个选项:

您可以检查文件扩展名:

static bool HasJpegExtension(string filename)
{
    // add other possible extensions here
    return Path.GetExtension(filename).Equals(".jpg", StringComparison.InvariantCultureIgnoreCase)
        || Path.GetExtension(filename).Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase);
}

或检查文件头中的正确幻数:

static bool HasJpegHeader(string filename)
{
    using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read)))
    {
        UInt16 soi = br.ReadUInt16();  // Start of Image (SOI) marker (FFD8)
        UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) or EXIF marker(FFE1)

        return soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff;
    }
}

另一种选择是加载图像并检查正确的类型。但是,这效率较低(除非您仍然要加载图像),但可能会给您最可靠的结果(请注意加载和解压缩的额外成本以及可能的异常处理):

static bool IsJpegImage(string filename)
{
    try
    {
        using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename)) 
        {           
            // Two image formats can be compared using the Equals method
            // See http://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat.aspx
            //
            return img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg);
        }
    }
    catch (OutOfMemoryException)
    {
        // Image.FromFile throws an OutOfMemoryException 
        // if the file does not have a valid image format or
        // GDI+ does not support the pixel format of the file.
        //
        return false;
    }
}
于 2009-04-21T13:06:25.060 回答
28

将文件作为流打开并查找 JPEG 的幻数

JPEG 图像文件以 FF D8 开头,以 FF D9 结尾。JPEG/JFIF 文件包含 'JFIF' (4A 46 49 46) 的 ASCII 代码作为空终止字符串。JPEG/Exif 文件包含 'Exif' (45 78 69 66) 的 ASCII 码,也作为空字符终止的字符串

于 2009-04-21T12:51:35.783 回答
27

OMG,这么多代码示例是错误的,错误的错误。

EXIF 文件的标记为 0xff* e1 *,JFIF 文件的标记为 0xff* e0 *。因此,所有依赖 0xffe0 来检测 JPEG 文件的代码都会丢失所有 EXIF 文件。

这是一个可以检测两者的版本,并且可以轻松更改为仅返回 JFIF 或仅返回 EXIF。(例如,在尝试恢复 iPhone 图片时很有用)。

    public static bool HasJpegHeader(string filename)
    {
        try
        {
            // 0000000: ffd8 ffe0 0010 4a46 4946 0001 0101 0048  ......JFIF.....H
            // 0000000: ffd8 ffe1 14f8 4578 6966 0000 4d4d 002a  ......Exif..MM.*    
            using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.ReadWrite)))
            {
                UInt16 soi = br.ReadUInt16();  // Start of Image (SOI) marker (FFD8)
                UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) EXIF marker (FFE1)
                UInt16 markerSize = br.ReadUInt16(); // size of marker data (incl. marker)
                UInt32 four = br.ReadUInt32(); // JFIF 0x4649464a or Exif  0x66697845

                Boolean isJpeg = soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff;
                Boolean isExif = isJpeg && four == 0x66697845;
                Boolean isJfif = isJpeg && four == 0x4649464a;

                if (isJpeg) 
                {
                    if (isExif)
                        Console.WriteLine("EXIF: {0}", filename);
                    else if (isJfif)
                        Console.WriteLine("JFIF: {0}", filename);
                    else
                        Console.WriteLine("JPEG: {0}", filename);
                }

                return isJpeg;
                return isJfif;
                return isExif;
            }
        }
        catch
        {
            return false;
        }
    }
于 2012-01-06T08:08:17.980 回答
13

您可以尝试将文件加载到图像中,然后检查格式

Image img = Image.FromFile(filePath);
bool isBitmap = img.RawFormat.Equals(ImageFormat.Jpeg);

或者,您可以打开文件并检查标题以获取类型

于 2009-04-21T12:51:50.277 回答
4

您可以找到有关 jpeg 文件格式的文档,特别是标题信息。然后尝试从文件中读取此信息并将其与预期的 jpeg 标头字节进行比较。

于 2009-04-21T12:49:00.000 回答
3

读取头字节。本文包含有关几种常见图像格式的信息,包括 JPEG:

使用图像文件头验证图像格式

JPEG 标头信息

于 2009-04-21T12:53:12.627 回答
1

一旦你有了扩展,你就可以使用正则表达式来验证它。

^.*\.(jpg|JPG)$
于 2009-04-21T12:50:35.787 回答
1

这将遍历当前目录中的每个文件,如果找到的任何带有 JPG 或 JPEG 扩展名的文件是 Jpeg 图像,则会输出。

      foreach (FileInfo f in new DirectoryInfo(".").GetFiles())
        {
            if (f.Extension.ToUpperInvariant() == ".JPG"
                || f.Extension.ToUpperInvariant() == ".JPEG")
            {
                Image image = Image.FromFile(f.FullName);

                if (image.RawFormat == ImageFormat.Jpeg)
                {
                    Console.WriteLine(f.FullName + " is a Jpeg image");
                }
            }
        }
于 2009-04-21T12:58:26.907 回答
1

根据您查看此文件的上下文,您需要记住,在用户告诉您打开文件之前,您无法打开该文件。

(链接是 Raymond Chen 的博客条目。)

于 2009-04-21T13:03:36.673 回答
0

这里的代码:

http://mark.michaelis.net/Blog/RetrievingMetaDataFromJPEGFilesUsingC.aspx

向您展示如何获取元数据。我想如果您的图像不是有效的 JPEG,那会引发异常。

于 2009-04-21T12:50:17.720 回答
0

检查文件扩展名是不够的,因为文件名可能是谎言。

一种快速而肮脏的方法是尝试使用 Image 类加载图像并捕获任何异常:

Image image = Image.FromFile(@"c:\temp\test.jpg");

这并不理想,因为您可能会遇到任何类型的异常,例如 OutOfMemoryException、FileNotFoundException 等。

最彻底的方法是将文件视为二进制文件并确保标头与 JPG 格式匹配。我敢肯定它在某处被描述过。

于 2009-04-21T12:54:55.947 回答
0

最好的方法是尝试使用 Drawing.Bitmap (string) 构造函数从中创建图像,看看它是否失败或抛出异常。一些答案的问题是这样的:首先,扩展名纯粹是任意的,它可能是 jpg、jpeg、jpe、bob、tim 等等。其次,仅使用标题不足以 100% 确定。它肯定可以确定文件不是 jpeg 但不能保证文件是 jpeg,任意二进制文件在开始时可能具有相同的字节序列。

于 2009-04-21T12:55:10.237 回答
0

只需获取文件的媒体类型并验证:

private bool isJpeg()
        {
string p = currFile.Headers.ContentType.MediaType;
            return p.ToLower().Equals("image/jpeg") || p.ToLower().Equals("image/pjpeg") || p.ToLower().Equals("image/png");
        }
于 2014-08-19T15:09:40.400 回答
0

在检查文件扩展后,像这样读取图像的前四个字节和图像的最后两个字节,为值 255 的最后两个字节执行此操作,其他文件为 217 可以执行此 操作在 C# http://www.garykessler中验证文件中的图像.net/library/file_sigs.html

// after check extention of file
byte[] ValidFileSignture = new byte[] { 255, 216, 255, 224 };
byte[] bufferforCheck = new byte[ValidFileSignture.Length];
Stream _inputStream = file.InputStream;
byte[] bufferforCheck1 = new byte[] { 255, 216, 255, 224 };
_inputStream.Read(bufferforCheck, 0, ValidFileSignture.Length);
if (!Enumerable.SequenceEqual(bufferforCheck, ValidFileSignture))
{
    //file OK
}
于 2015-02-23T12:38:55.490 回答
0
System.Web.MimeMapping.GetMimeMapping(filename).StartsWith("image/");
MimeMapping.GetMimeMapping produces these results:

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
于 2016-11-09T13:25:37.003 回答
-1

您可以使用Path.GetExtension 方法

于 2009-04-21T12:48:20.423 回答