determine if file is an image
Check the file for a known header. (Info from link also mentioned in this answer)
The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10
Check out System.IO.Path.GetExtension
Here is a quick sample.
public static readonly List<string> ImageExtensions = new List<string> { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG" };
private void button_Click(object sender, RoutedEventArgs e)
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var files = Directory.GetFiles(folder);
foreach(var f in files)
{
if (ImageExtensions.Contains(Path.GetExtension(f).ToUpperInvariant()))
{
// process image
}
}
}
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
file.svg not returning an image/ MIME type works out in most cases because you're probably not going to process a vector image like you would a scalar image. When checking MIME type, do be aware that SVG does have the standard MIME type of image/svg+xml, even if GetMimeMapping
doesn't return it.
This will look at the first few bytes of a file and determine whether it is an image.
using System.Collections.Generic;
using System.IO;
using System.Linq;
public static class Extension
{
public static bool IsImage(this Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
List<string> jpg = new List<string> { "FF", "D8" };
List<string> bmp = new List<string> { "42", "4D" };
List<string> gif = new List<string> { "47", "49", "46" };
List<string> png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
List<List<string>> imgTypes = new List<List<string>> { jpg, bmp, gif, png };
List<string> bytesIterated = new List<string>();
for (int i = 0; i < 8; i++)
{
string bit = stream.ReadByte().ToString("X2");
bytesIterated.Add(bit);
bool isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
if (isImage)
{
return true;
}
}
return false;
}
}
Edit
I've made a few changes to the above to allow you to add your own images if you needed to, also removed collections which weren't necessary to begin with. I also added an overload accepting an out
parameter of type string
, setting the value to the type of image the stream is composed of.
public static class Extension
{
static Extension()
{
ImageTypes = new Dictionary<string, string>();
ImageTypes.Add("FFD8","jpg");
ImageTypes.Add("424D","bmp");
ImageTypes.Add("474946","gif");
ImageTypes.Add("89504E470D0A1A0A","png");
}
/// <summary>
/// <para> Registers a hexadecimal value used for a given image type </para>
/// <param name="imageType"> The type of image, example: "png" </param>
/// <param name="uniqueHeaderAsHex"> The type of image, example: "89504E470D0A1A0A" </param>
/// </summary>
public static void RegisterImageHeaderSignature(string imageType, string uniqueHeaderAsHex)
{
Regex validator = new Regex(@"^[A-F0-9]+$", RegexOptions.CultureInvariant);
uniqueHeaderAsHex = uniqueHeaderAsHex.Replace(" ", "");
if (string.IsNullOrWhiteSpace(imageType)) throw new ArgumentNullException("imageType");
if (string.IsNullOrWhiteSpace(uniqueHeaderAsHex)) throw new ArgumentNullException("uniqueHeaderAsHex");
if (uniqueHeaderAsHex.Length % 2 != 0) throw new ArgumentException ("Hexadecimal value is invalid");
if (!validator.IsMatch(uniqueHeaderAsHex)) throw new ArgumentException ("Hexadecimal value is invalid");
ImageTypes.Add(uniqueHeaderAsHex, imageType);
}
private static Dictionary<string, string> ImageTypes;
public static bool IsImage(this Stream stream)
{
string imageType;
return stream.IsImage(out imageType);
}
public static bool IsImage(this Stream stream, out string imageType)
{
stream.Seek(0, SeekOrigin.Begin);
StringBuilder builder = new StringBuilder();
int largestByteHeader = ImageTypes.Max(img => img.Value.Length);
for (int i = 0; i < largestByteHeader; i++)
{
string bit = stream.ReadByte().ToString("X2");
builder.Append(bit);
string builtHex = builder.ToString();
bool isImage = ImageTypes.Keys.Any(img => img == builtHex);
if (isImage)
{
imageType = ImageTypes[builder.ToString()];
return true;
}
}
imageType = null;
return false;
}
}