I have an image resized program and it works. The problem is when a user selects a non-image file in the file select dialog, it crashes. How can I check for image files?
-
2Related: [C# How can I test a file is a jpeg?](http://stackoverflow.com/questions/772388/c-how-can-i-test-a-file-is-a-jpeg/772492#772492). Your problem is very similar, you only have to add additional checks if you want to support further formats. – Dirk Vollmar Aug 24 '10 at 15:06
-
The best way to achieve what you wnat is what's suggested by 0xA3. Wrap the Image.FromFile in a Try block. If it's a valid image, you'll get the image output. If it isn't a valid image, you'll get an OutOfMemory Exception and your code will be safe. – Alex Essilfie Aug 24 '10 at 16:55
-
(again): If you insist you want VB, check my solution. – Alex Essilfie Aug 24 '10 at 16:57
5 Answers
UPDATE: 2022-04-05
Since it may not be feasible to validate the binary structure of every supported image, the fastest way to check if a file contains an image is to actually load it. If it loads successfully, then it is valid. If it doesn't then it is not.
The code below can be used to check if a file contains a valid image or not. This code is updated to prevent locking the file while the method is called. It also handles resource disposal after the tests (thanks for pointing out this issue user1931470).
Public Function IsValidImage(fileName As String) As Boolean
Dim img As Drawing.Image = Nothing
Dim isValid = False
Try
' Image.FromFile locks the file until the image is disposed.
' This might not be the wanted behaviour so it is preferable to
' open the file stream and read the image from it.
Using stream = New System.IO.FileStream(fileName, IO.FileMode.Open)
img = Drawing.Image.FromStream(stream)
isValid = True
End Using
Catch oome As OutOfMemoryException
' Image.FromStream throws an OutOfMemoryException
' if the file does not have a valid image format.
isValid = False
Finally
' clean up resources
If img IsNot Nothing Then img.Dispose()
End Try
Return isValid
End Function
ORIGINAL ANSWER
⚠️⚠️ WARNING ⚠️⚠️
This code has a bug that causes a high memory consumption when called several times in a program's lifetime.
DO NOT USE THIS CODE!!
Here's the VB.NET equivalent of 0xA3's answer since the OP insisted on a VB version.
Function IsValidImage(filename As String) As Boolean
Try
Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
Catch generatedExceptionName As 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
End Try
Return True
End Function
You use it as follows:
If IsValidImage("c:\path\to\your\file.ext") Then
'do something
'
Else
'do something else
'
End If
Edit:
I don't recommend you check file extensions. Anyone can save a different file (text document for instance) with a .jpg
extension and trick you app into beleiving it is an image.
The best way is to load the image using the function above or to open the first few bytes and check for the JPEG signature.
You can find more information about JPEG files and their headers here:

- 12,339
- 9
- 70
- 108
-
Ordinarily I wouldn't have done this but the OP insisted so I had to. You deserve the credit anyway as you answered earlier. – Alex Essilfie Aug 24 '10 at 17:12
-
1fair warning I used this in one of my recent projects to make a slideshow application, but after passing a bunch of image files through it my applications memory usage was going into the GB range, i was able to fix this by adding img.Dispose() after the Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename) – user1931470 Apr 02 '22 at 22:54
-
@user1931470: Thanks for the catch. I've updated the code accordingly. – Alex Essilfie Apr 05 '22 at 14:07
A very primitive check is to simply try to load the image. If it is not valid an OutOfMemoryException
will be thrown:
static bool IsImageValid(string filename)
{
try
{
System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
}
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;
}
return true;
}
If I understood your question correctly your application it going to load the image anyway. Therefore simply wrapping the load operation in a try/catch block does not mean any additional overhead. For the VB.NET solution of this approach check the answer by @Alex Essilfie.
The ones wondering why Image.FromFile
is throwing an OOM on invalid files should read the answer of Hans Passant to the following question:
Is there a reason Image.FromFile throws an OutOfMemoryException for an invalid image format?

- 1
- 1

- 172,527
- 53
- 255
- 316
-
-
@Dan Tao: The reason for this is the mapping of the old Windows error code 3 (FILE_NOT_FOUND) which is returned by the native GDI+ function that loads image (error codes were rather limited and it was not easy to add new ones like INVALID_IMAGE_FORMAT). I don't know exactly why it has been mapped to an `OutOfMemoryException` but I assume there was reason for it. – Dirk Vollmar Aug 24 '10 at 15:55
Your first line of defense, of course, would be simply to check the file's extension:
Function IsImageFile(ByVal filename As String) As Boolean
Dim ext As String = Path.GetExtension(filename).ToLowerInvariant()
' This supposes your program can deal only with JPG files; '
' you could add other extensions here as necessary. '
Return ext = ".jpg" OrElse ext = ".jpeg"
End Function
Better yet, as SLC suggests in a comment, set your dialog's Filter
property:
dialog.Filter = "Image files|*.jpg;*.jpeg"
This isn't a guarantee -- ideally you'd want to check the file itself to verify it's an image, and theoretically you should also be able to load files with anomalous extensions if they are in fact image files (maybe just ask for the user's acknowledgement first) -- but it's an easy start.

- 125,917
- 54
- 300
- 447
-
1
-
It would be better to check for other case variants of the extension using `string.Equals(ext, ".jpg", StringComparison.InvariantCultureIgnoreCase)`. – Dirk Vollmar Aug 24 '10 at 15:16
-
@0xA3: In short little methods like this I tend to go with `ToLower` as it's less typing than writing out potentially several `string.Equals` method calls. – Dan Tao Aug 24 '10 at 15:20
-
`ToLower()` is fine for simple samples like this. However, not only that a new string object is created, it is also not safe and failes the [Turkey Test](http://www.codinghorror.com/blog/2008/03/whats-wrong-with-turkey.html). At least one should use `ToLowerInvariant()` in production code. – Dirk Vollmar Aug 24 '10 at 15:45
-
@0xA3: Yes, a new string is created; but considering it's likely to be 3-5 characters, I wouldn't sweat it. It's still vastly preferable (in my opinion) to typing `ext.Equals(".jpg", StringComparison.InvariantCultureIgnoreCase) || ext.Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase) || [...]` -- obviously in a performance-critical scenario, things would be different. I had forgotten about the Turkey test, though! – Dan Tao Aug 24 '10 at 16:00
-
That depends. You usually would also have to cater for a `NullReferenceException` (here if your file doesn't have an extension). Something you don't need to do with the static `string.Equals` method. – Dirk Vollmar Aug 24 '10 at 16:18
-
@0xA3: I used to always include all the defensive checks and throw appropriate exceptions whenever I posted code on SO; eventually I realized I was doing a lot of typing that wasn't really relevant to the OP's question. So I've tried to kick that habit in favor of just posting whatever's directly relevant to the question. This is just a long way of explaining why I didn't bother including `if (string.IsNullOrEmpty(filename)) return false;` -- after all, there's no point calling `string.Equals` over and over on a null string. – Dan Tao Aug 24 '10 at 17:13
-
@0xA3: By the way `Path.GetExtension` only returns `null` if it's *passed* `null`; so the scenario of a filename without an extension wouldn't be problematic. – Dan Tao Aug 24 '10 at 17:17
The VB and C# answers are great but also contain a "gotcha" if you plan to alter or move the file: the created 'img' object will lock the image file unless the dispose() method is invoked to release it. See below:
VB
Function IsValidImage(filename As String) As Boolean
Try
Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
img.dispose() ' Removes file-lock of IIS
Catch generatedExceptionName As 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
End Try
Return True
End Function
C#
static bool IsImageValid(string filename)
{
try
{
System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
img.dispose(); // Removes file-lock of IIS
}
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;
}
return true;
}

- 541
- 1
- 6
- 18
The most robust way would be to understand the signatures of the files you need to load.
JPEG has a particular header format, for example.
This way your code won't be as easily fooled if you just look at the extension.
163's answer should get you most of the way along these lines.

- 15,990
- 10
- 70
- 110
-
a simple extension filter would be a good first start, but you would want something like this after, just to make sure that renamed files don't slip through, but of course, encapsulating it all inside a try/catch statement would be a final test to make sure that the result won't crash your program. The more error checking, the better (to some degree anyway). – MaQleod Aug 24 '10 at 15:17