Search code examples
.netimagefile-formatfile-type

How can I determine if a file is an image file in .NET?


I don't want to rely on the file extension. I don't care to know what type of image it is (.jpg, .png, etc.), I simply want to know if the file is an image or not. I'd prefer to not use any non-.NET dlls if possible.

The best way I know how to do this is the following:

bool isImageFile;
try
{
    Image.FromFile(imageFile).Dispose();
    isImageFile = true;
}
catch (OutOfMemoryException)
{
    isImageFile = false;
}

As noted here: http://msdn.microsoft.com/en-us/library/stf701f5.aspx, Image.FromFile() throws an OutOfMemoryException if the file isn't a valid image format. Using the above gives me exactly the result I want, however I'd prefer not to use it for the following reasons:

  • It is my belief that using try-catches for normal program execution is a bad practice for performance reasons.
  • Image.FromFile() loads the whole image file (if it is an image file) into memory. This is wasteful I assume because I only need the file type and don't need to do any further image manipulation at this point in my code.
  • I dislike catching OutOfMemoryExceptions because what if there is a REAL out-of-memory problem and my program swallows it and keeps going?

Are there any better ways to do this? Or, are any/all of my concerns listed above unwarranted?

Edit: Since receiving the answers here, these are the three solutions I'm now aware of:

  1. Load the whole image in memory via Image.FromFile() and a try-catch.
    • Pros: Does a deeper check against the image files contents; covers many image types.
    • Cons: Slowest; overhead from try-catch and loading full image file into memory; potential danger from catching a 'real' OutOfMemoryException.
  2. Check the header bytes of the image file.
    • Pros: Quick, low memory usage.
    • Cons: potentially brittle; need to program for every file type.
  3. Check the file extension.
    • Pros: Quickest; simplest.
    • Cons: Doesn't work in all situations; most easily wrong.

(I do not see a clear "winner" since I can imagine a situation in which each one would be appropriate. For my application's purposes, the file type checking happens infrequently enough that the performance concerns of method 1 weren't an issue.)


Solution

    1. You will only notice a performance hit from exceptions if you are constantly throwing them. So unless your program expects to see many invalid images (hundreds per second) you should not notice the overhead of exception handling.
    2. This is really the only way to tell if the image is a full image or corrupt. You can check the headers as the other people recommend, but that only checks to see if the beginning few bytes are correct, anything else could be garbage. Whether this is good enough or not depends on the requirements of your application. Just reading the header might be good enough for your use case.
    3. Yes, this is rather poor design on the BCL team's part. If you are loading many large images you very well could be hitting a real OOM situation in the large object heap. As far as I know, there is no way to differentiate the two exceptions.