I'm loading an image from a file, and I want to know how to validate the image before it is fully read from the file.
string filePath = "image.jpg";
Image newImage = Image.FromFile(filePath);
The problem occurs when image.jpg isn't really a jpg. For example, if I create an empty text file and rename it to image.jpg, an OutOfMemory Exception will be thrown when image.jpg is loaded.
I'm looking for a function that will validate an image given a stream or a file path of the image.
Example function prototype
bool IsValidImage(string fileName);
bool IsValidImage(Stream imageStream);
JPEG's don't have a formal header definition, but they do have a small amount of metadata you can use.
There are a couple other things after that, but those aren't important.
You can open the file using a binary stream, and read this initial data, and make sure that OffSet 0 is 0, and OffSet 6 is either 1,2 or 3.
That would at least give you slightly more precision.
Or you can just trap the exception and move on, but I thought you wanted a challenge :)
here is my image check. I cannot rely on file extensions and have to check the format on my own. I am loading BitmapImages in WPF from byte arrays and don't know the format upfront. WPF detects the format fine but does not tell you the image format of BitmapImage objects (at least I am not aware of a property for this). And I don't want load the image again with System.Drawing only to detect the format. This solution is fast and works fine for me.
public enum ImageFormat
{
bmp,
jpeg,
gif,
tiff,
png,
unknown
}
public static ImageFormat GetImageFormat(byte[] bytes)
{
// see http://www.mikekunz.com/image_file_header.html
var bmp = Encoding.ASCII.GetBytes("BM"); // BMP
var gif = Encoding.ASCII.GetBytes("GIF"); // GIF
var png = new byte[] { 137, 80, 78, 71 }; // PNG
var tiff = new byte[] { 73, 73, 42 }; // TIFF
var tiff2 = new byte[] { 77, 77, 42 }; // TIFF
var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon
if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
return ImageFormat.bmp;
if (gif.SequenceEqual(bytes.Take(gif.Length)))
return ImageFormat.gif;
if (png.SequenceEqual(bytes.Take(png.Length)))
return ImageFormat.png;
if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
return ImageFormat.tiff;
if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
return ImageFormat.tiff;
if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
return ImageFormat.jpeg;
if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
return ImageFormat.jpeg;
return ImageFormat.unknown;
}