Skip to content

Instantly share code, notes, and snippets.

@ChuckSavage
Created August 29, 2017 18:29
Show Gist options
  • Save ChuckSavage/dc079e21563ba1402cf6c907d81ac1ca to your computer and use it in GitHub Desktop.
Save ChuckSavage/dc079e21563ba1402cf6c907d81ac1ca to your computer and use it in GitHub Desktop.
C# Is file an image and get its type
// Includes a mini-program for checking and fixing files that have no extension
// Only checks for the most common types
// If you create a better version, please upload it here.
using System;
using System.Collections.Generic;
using System.IO;
namespace AppendJPG
{
class Program
{
static void Main(string[] args)
{
foreach (string file in Directory.EnumerateFiles(Environment.CurrentDirectory))
{
//var x = Path.GetExtension(file);
if (Path.GetExtension(file).Length == 0)
{
//var n = Path.GetFileNameWithoutExtension(file);
IsImageExtension.ImageType type;
if (file.IsImage(out type))
{
var ext = type.ToString().ToLower();
//Console.WriteLine(ext);
File.Move(file, file + "." + ext);
}
//var t = type;
}
}
}
}
public static class IsImageExtension
{
static List<string> jpg;
static List<string> bmp;
static List<string> gif;
static List<string> png;
public enum ImageType
{
JPG,
BMP,
GIF,
PNG,
NONE
}
const string JPG = "FF";
const string BMP = "42";
const string GIF = "47";
const string PNG = "89";
static IsImageExtension()
{
jpg = new List<string> { "FF", "D8" };
bmp = new List<string> { "42", "4D" };
gif = new List<string> { "47", "49", "46" };
png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
}
public static bool IsImage(this string file, out ImageType type)
{
type = ImageType.NONE;
if (string.IsNullOrWhiteSpace(file)) return false;
if (!File.Exists(file)) return false;
using (var stream = File.OpenRead(file))
return stream.IsImage(out type);
}
public static bool IsImage(this Stream stream, out ImageType type)
{
type = ImageType.NONE;
stream.Seek(0, SeekOrigin.Begin);
string bit = stream.ReadByte().ToString("X2");
switch (bit)
{
case JPG:
if (stream.IsImage(jpg))
{
type = ImageType.JPG;
return true;
}
break;
case BMP:
if (stream.IsImage(bmp))
{
type = ImageType.BMP;
return true;
}
break;
case GIF:
if (stream.IsImage(gif))
{
type = ImageType.GIF;
return true;
}
break;
case PNG:
if (stream.IsImage(png))
{
type = ImageType.PNG;
return true;
}
break;
default:
break;
}
return false;
}
public static bool IsImage(this Stream stream, List<string> comparer)
{
stream.Seek(0, SeekOrigin.Begin);
foreach (string c in comparer)
{
string bit = stream.ReadByte().ToString("X2");
if (0 != string.Compare(bit, c))
return false;
}
return true;
}
}
}
@EvilVir
Copy link

EvilVir commented Sep 7, 2022

@Freshmintyy they are wildly available on the Internet. One is on Wikipedia: https://en.m.wikipedia.org/wiki/List_of_file_signatures

Other one: https://www.garykessler.net/library/file_sigs.html

Search for Magic Numbers, File Headers etc. there are also nugets for .NET that have these lists and functions to check. Be aware that there are thousands and thousands file types, checking them all without any index would be very slow and resource hungry. Therefore either use indexes, divide for parallel processing etc. or, in cases such as this, just pick couple of signatures you really need and check only against them.

@jasarsoft
Copy link

jasarsoft commented Jun 23, 2023

Hi @EvilVir
We have a small error here.
When the appropriate code is found in the header, it is necessary to return the stream to the beginning before the return statement.

if (slice.SequenceEqual(check.Value))
{
data.Seek(0, SeekOrigin.Begin);
return check.Key;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment