tags:

views:

2834

answers:

12

Using C# how can I test a file is a jpeg? Should I check for a .jpg extension?

Thanks

+2  A: 

You can use the Path.GetExtension Method.

Galwegian
+4  A: 

You could find documentation on the jpeg file format, specifically the header information. Then try to read this information from the file and compare it to the expected jpeg header bytes.

Brian Ensink
A: 

The code here:

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

Shows you how to get the Meta Data. I guess that would throw an exception if your image wasn't a valid JPEG.

Program.X
+2  A: 

Once you have the extension you could use a regular expression to validate it.

^.*\.(jpg|JPG)$
Shaun Humphries
Should include `jpeg` in there as well, and probably spend a minute searching for other less common jpeg file extensions.
Brian Ensink
+20  A: 

Open the file as a stream and look for the magic number for JPEG.

JPEG image files begin with FF D8 and end with FF D9. JPEG/JFIF files contain the ASCII code for 'JFIF' (4A 46 49 46) as a null terminated string. JPEG/Exif files contain the ASCII code for 'Exif' (45 78 69 66) also as a null terminated string

Simon Gibbs
+11  A: 

You could try loading the file into an Image and then check the format

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

Alternatively you could open the file and check the header to get the type

Lee
For each positive case, you'd have decoded the whole image when you might not want to, and for each negative case I expect you'd need to handle an exception - driving the poor guy debugging your code mental hammering on F5. I guess it depends on the scenario but there are other answers that don't have these issues.
Simon Gibbs
The comparison actually fails. You need to call `ImageFormat.Equals` instead of using the `==` operator.
0xA3
I corrected the error in the code.
0xA3
+3  A: 

Read the header bytes. This article contains info on several common image formats, including JPEG:

Using Image File Headers To Verify Image Format

JPEG Header Information

Mitch Wheat
A: 

Checking the file extension is not enough as the filename might be lying.

A quick and dirty way is to try and load the image using the Image class and catching any exceptions:

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

This isn't ideal as you could get any kind of exception, such as OutOfMemoryException, FileNotFoundException, etc. etc.

The most thorough way is to treat the file as binary and ensure the header matches the JPG format. I'm sure it's described somewhere.

Steve Dunn
A: 

The best way would to try and create an image from it using the Drawing.Bitmap (string) constructor and see if it fails to do so or throws an exception. The problem with some of the answers are this: firstly, the extension is purely arbitrary, it could be jpg, jpeg, jpe, bob, tim, whatever. Secondly, just using the header isn't enough to be 100% sure. It can definately determine that a file isn't a jpeg but can't guarantee that a file is a jpeg, an arbitrary binary file could have the same byte sequence at the start.

Skizz

Skizz
+1  A: 

This will loop through each file in the current directory and will output if any found files with JPG or JPEG extension are Jpeg images.

      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");
                }
            }
        }
Joe
+1  A: 

Depending on the context in which you're looking at this file, you need to remember that you can't open the file until the user tells you to open it.

(The link is to a Raymond Chen blog entry.)

Dave Webb
+36  A: 

Several options:

You can check for the file extension:

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

or check for the correct magic number in the header of the file:

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

        return soi == 0xd8ff && jfif == 0xe0ff;
    }
}

Another option would be to load the image and check for the correct type. However, this is less efficient (unless you are going to load the image anyway) but will probably give you the most reliable result (Be aware of the additional cost of loading and decompression as well as possible exception handling):

static bool IsJpegImage(string filename)
{
    try
    {
        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;
    }
}
0xA3
+1 for static bool IsJpegHeader(string filename)
Simon Gibbs
+1 for having written what I wanted to write, only better ;-)
Treb
+1 for comprehensive answer
Michael Haren
+1 for good answer with excellent sample.
Erik van Brakel
+1 for being more diligent. Couple of ideas: I would rename to HasJpegExtension and ContainsJpegHeader. Also,wouldn't you want catch other exceptions in case the file was deleted/moved/etc between checking the ext/header and trying to load it? or would it be better to just bubble all of them up?
Erich Mirabal
Surely the naming can be improved and should be adjusted to your actual use case. In this simple example I simply chose to add the specific way used as a suffix. In the end I probably would just use `IsJpeg` or some of your suggestions. Since it is a simple example I didn't want to overload it with exception handling, but typically I would handle exceptions related to file io and access permissions higher up in the stack.
0xA3