我循环遍历目录并复制所有文件.现在我做string.EndsWith
检查".jpg"
或".png"
等..
有没有更优雅的方法来确定文件是否是一个图像(任何图像类型)没有上面的hacky检查?
检查文件是否有已知标头.(链接中的信息也在这个答案中提到)
PNG文件的前八个字节始终包含以下(十进制)值:137 80 78 71 13 10 26 10
查看System.IO.Path.GetExtension
这是一个快速的样本.
public static readonly ListImageExtensions = new List { ".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 } } }
这将查看文件的前几个字节并确定它是否是图像.
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); Listjpg = new List { "FF", "D8" }; List bmp = new List { "42", "4D" }; List gif = new List { "47", "49", "46" }; List png = new List { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" }; List > imgTypes = new List
> { jpg, bmp, gif, png }; List
bytesIterated = new List (); 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; } }
我对上面的内容进行了一些更改,以便您可以根据需要添加自己的图像,还可以删除不必要的集合.我还添加了一个接受out
类型参数的重载string
,将值设置为流组成的图像类型.
public static class Extension { static Extension() { ImageTypes = new Dictionary(); ImageTypes.Add("FFD8","jpg"); ImageTypes.Add("424D","bmp"); ImageTypes.Add("474946","gif"); ImageTypes.Add("89504E470D0A1A0A","png"); } /// /// 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 DictionaryRegisters a hexadecimal value used for a given image type /// The type of image, example: "png" /// The type of image, example: "89504E470D0A1A0A" ///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; } }
System.Web.MimeMapping.GetMimeMapping(filename).StartsWith("image/");
MimeMapping.GetMimeMapping
产生这些结果:
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不返回图像/ MIME类型,因为您可能不会像处理标量图像那样处理矢量图像.检查MIME类型时,请注意SVG确实具有标准MIME类型image/svg + xml,即使GetMimeMapping
它没有返回它.
我们可以使用命名空间System.Drawing中的图像和图形类; 做我们的工作.如果代码无错误地运行,则它是图像,否则不是.这就是让DotNet框架为我们工作.代码 -
public string CheckFile(file) { string result=""; try { System.Drawing.Image imgInput = System.Drawing.Image.FromFile(file); System.Drawing.Graphics gInput = System.Drawing.Graphics.fromimage(imgInput); Imaging.ImageFormat thisFormat = imgInput.RawFormat; result="It is image"; } catch(Exception ex) { result="It is not image"; } return result; }
如果您想要一种快速的方法来在完全从文件中读取图像文件之前对其进行验证,除了比较文件扩展名之外,您还可以检查其标题以查找文件签名(以下代码IsValidImageFile()
检查BMP,GIF87a,GIF89a,PNG, TIFF,JPEG)
////// Reads the header of different image formats /// /// Image file ///true if valid file signature (magic number/header marker) is found private bool IsValidImageFile(string file) { byte[] buffer = new byte[8]; byte[] bufferEnd = new byte[2]; var bmp = new byte[] { 0x42, 0x4D }; // BMP "BM" var gif87a = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }; // "GIF87a" var gif89a = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }; // "GIF89a" var png = new byte[] { 0x89, 0x50, 0x4e, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; // PNG "\x89PNG\x0D\0xA\0x1A\0x0A" var tiffI = new byte[] { 0x49, 0x49, 0x2A, 0x00 }; // TIFF II "II\x2A\x00" var tiffM = new byte[] { 0x4D, 0x4D, 0x00, 0x2A }; // TIFF MM "MM\x00\x2A" var jpeg = new byte[] { 0xFF, 0xD8, 0xFF }; // JPEG JFIF (SOI "\xFF\xD8" and half next marker xFF) var jpegEnd = new byte[] { 0xFF, 0xD9 }; // JPEG EOI "\xFF\xD9" try { using (System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { if (fs.Length > buffer.Length) { fs.Read(buffer, 0, buffer.Length); fs.Position = (int)fs.Length - bufferEnd.Length; fs.Read(bufferEnd, 0, bufferEnd.Length); } fs.Close(); } if (this.ByteArrayStartsWith(buffer, bmp) || this.ByteArrayStartsWith(buffer, gif87a) || this.ByteArrayStartsWith(buffer, gif89a) || this.ByteArrayStartsWith(buffer, png) || this.ByteArrayStartsWith(buffer, tiffI) || this.ByteArrayStartsWith(buffer, tiffM)) { return true; } if (this.ByteArrayStartsWith(buffer, jpeg)) { // Offset 0 (Two Bytes): JPEG SOI marker (FFD8 hex) // Offest 1 (Two Bytes): Application segment (FF?? normally ??=E0) // Trailer (Last Two Bytes): EOI marker FFD9 hex if (this.ByteArrayStartsWith(bufferEnd, jpegEnd)) { return true; } } } catch (Exception ex) { MessageBox.Show(ex.Message, Lang.Lang.ErrorTitle + " IsValidImageFile()", MessageBoxButtons.OK, MessageBoxIcon.Error); } return false; } ////// Returns a value indicating whether a specified subarray occurs within array /// /// Main array /// Subarray to seek within main array ///true if a array starts with b subarray or if b is empty; otherwise false private bool ByteArrayStartsWith(byte[] a, byte[] b) { if (a.Length < b.Length) { return false; } for (int i = 0; i < b.Length; i++) { if (a[i] != b[i]) { return false; } } return true; }
检查标头签名可能很快,因为它不会加载整个文件或创建大对象,特别是在处理多个文件时。但是它不会检查其余数据是否格式正确。为此,可以尝试将文件加载到Image
对象的第二步(这样可以确定文件可以由程序显示和处理)。
bool IsValidImage(string filename) { try { using(Image newImage = Image.FromFile(filename)) {} } catch (OutOfMemoryException ex) { //The file does not have a valid image format. //-or- GDI+ does not support the pixel format of the file return false; } return true; }
我使用以下方法。它使用内置的图像解码器检索系统识别为图像文件的扩展名列表,然后将这些扩展名与您传入的文件名的扩展名进行比较。返回简单的TRUE / FALSE。
public static bool IsRecognisedImageFile(string fileName) { string targetExtension = System.IO.Path.GetExtension(fileName); if (String.IsNullOrEmpty(targetExtension)) return false; else targetExtension = "*" + targetExtension.ToLowerInvariant(); ListrecognisedImageExtensions = new List (); foreach (System.Drawing.Imaging.ImageCodecInfo imageCodec in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()) recognisedImageExtensions.AddRange(imageCodec.FilenameExtension.ToLowerInvariant().Split(";".ToCharArray())); foreach (string extension in recognisedImageExtensions) { if (extension.Equals(targetExtension)) { return true; } } return false; }
看看这是否有帮助.
编辑:此外,Image.FromFile(....).RawFormat可能会有所帮助.如果文件不是图像,它可能会抛出异常.