This is awesome. I was so fed up with trying to find a fail-proof, cross-platform way to find the mime type of an image using PHP that I wrote a quick function that utilizes the same technology as the exif_imagetype, getimagesize, and finfo functions do.

Basically, the method is the exact same as that used by all magic file type enumerators. Just open the file/stream in read-binary mode and grab the file header (the first few bytes). I opted to keep it simple and super-fast and just used ==, otherwise you can use preg_match with the /s.

This is also the same method used by imagemagick, Apache, really everything that does it low-level.

Use the return as the arg to image_type_to_mime_type to get the mime string.

<?php
// oh no he didnt
function askapache_get_image_filetype( $file ) {
if ( !
is_file( $file ) || ! is_readable( $file ) )
return
false;

if (
false === $fp = fopen( $file, 'rb' ) )
return
false;

if (
false === $file_size = filesize( $file ) )
return
false;

if (
$file_size < 13 )
return
false;

if (
false === $line = fread( $fp, 12 ) )
return
false;

fclose( $fp );

$l2 = substr( $line, 0, 2 );
$l3 = substr( $line, 0, 3 );
$l4 = substr( $line, 0, 4 );
$l7 = substr( $line, 0, 7 );
$l8 = substr( $line, 0, 8 );


static
$define_imagetypes = false;
if ( !
$define_imagetypes ) {
!
defined( 'IMAGETYPE_UNKNOWN' ) && define( 'IMAGETYPE_UNKNOWN', 0 );
!
defined( 'IMAGETYPE_GIF' ) && define( 'IMAGETYPE_GIF', 1 );
!
defined( 'IMAGETYPE_JPEG' ) && define( 'IMAGETYPE_JPEG', 2 );
!
defined( 'IMAGETYPE_PNG' ) && define( 'IMAGETYPE_PNG', 3 );
!
defined( 'IMAGETYPE_SWF' ) && define( 'IMAGETYPE_SWF', 4 );
!
defined( 'IMAGETYPE_PSD' ) && define( 'IMAGETYPE_PSD', 5 );
!
defined( 'IMAGETYPE_BMP' ) && define( 'IMAGETYPE_BMP', 6 );
!
defined( 'IMAGETYPE_TIFF_II' ) && define( 'IMAGETYPE_TIFF_II', 7 );
!
defined( 'IMAGETYPE_TIFF_MM' ) && define( 'IMAGETYPE_TIFF_MM', 8 );
!
defined( 'IMAGETYPE_JPC' ) && define( 'IMAGETYPE_JPC', 9 );
!
defined( 'IMAGETYPE_JP2' ) && define( 'IMAGETYPE_JP2', 10 );
!
defined( 'IMAGETYPE_JPX' ) && define( 'IMAGETYPE_JPX', 11 );
!
defined( 'IMAGETYPE_JB2' ) && define( 'IMAGETYPE_JB2', 12 );
!
defined( 'IMAGETYPE_SWC' ) && define( 'IMAGETYPE_SWC', 13 );
!
defined( 'IMAGETYPE_IFF' ) && define( 'IMAGETYPE_IFF', 14 );
!
defined( 'IMAGETYPE_WBMP' ) && define( 'IMAGETYPE_WBMP', 15 );
!
defined( 'IMAGETYPE_XBM' ) && define( 'IMAGETYPE_XBM', 16 );
!
defined( 'IMAGETYPE_ICO' ) && define( 'IMAGETYPE_ICO', 17 );
$define_imagetypes = true;
}


$image_type_num = IMAGETYPE_UNKNOWN;
if (
$l2 == 'BM' ) {
$image_type_num = IMAGETYPE_BMP;
} elseif (
$l3 == "\377\330\377" ) {
$image_type_num = IMAGETYPE_JPEG;
} elseif (
$l3 == 'GIF' ) {
$image_type_num = IMAGETYPE_GIF;
} elseif (
$l4 == "\000\000\001\000" ) {
$image_type_num = IMAGETYPE_ICO;
} elseif (
$l4 == "II\052\000" ) {
$image_type_num = IMAGETYPE_TIFF_II;
} elseif (
$l4 == "MM\000\052" ) {
$image_type_num = IMAGETYPE_TIFF_MM;
} elseif (
$l7 == '#define' ) {
$image_type_num = IMAGETYPE_XBM;
} elseif (
$l8 == "\211\120\116\107\015\012\032\012" ) {
$image_type_num = IMAGETYPE_PNG;
}

return
$image_type_num;
}
?>

This is well 1000x more efficient than a exec like system('file -i -b --mime-type $f'); could ever be.. (and you should disabled exec functions like that anyway).

And from the source php-5.4.13

<?php
// file type markers
PHPAPI const char php_sig_gif[3] = {'G', 'I', 'F'};
PHPAPI const char php_sig_psd[4] = {'8', 'B', 'P', 'S'};
PHPAPI const char php_sig_bmp[2] = {'B', 'M'};
PHPAPI const char php_sig_swf[3] = {'F', 'W', 'S'};
PHPAPI const char php_sig_swc[3] = {'C', 'W', 'S'};
PHPAPI const char php_sig_jpg[3] = { 0xff, 0xd8, 0xff};
PHPAPI const char php_sig_png[8] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
PHPAPI const char php_sig_tif_ii[4] = {'I','I', 0x2A, 0x00};
PHPAPI const char php_sig_tif_mm[4] = {'M','M', 0x00, 0x2A};
PHPAPI const char php_sig_jpc[3] = { 0xff, 0x4f, 0xff};
PHPAPI const char php_sig_jp2[12] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a};
PHPAPI const char php_sig_iff[4] = {'F','O','R','M'};
PHPAPI const char php_sig_ico[4] = { 0x00, 0x00, 0x01, 0x00};

1 IMAGETYPE_GIF
2 IMAGETYPE_JPEG
3 IMAGETYPE_PNG
4 IMAGETYPE_SWF
5 IMAGETYPE_PSD
6 IMAGETYPE_BMP
7 IMAGETYPE_TIFF_II
(intel byte order)
8 IMAGETYPE_TIFF_MM (motorola byte order)
9 IMAGETYPE_JPC
10 IMAGETYPE_JP2
11 IMAGETYPE_JPX
12 IMAGETYPE_JB2
13 IMAGETYPE_SWC
14 IMAGETYPE_IFF
15 IMAGETYPE_WBMP
16 IMAGETYPE_XBM
17 IMAGETYPE_ICO
?>

And from imagemagick

static const MagicMapInfo
  MagicMap[] =
  {
    { "8BIMWTEXT", 0, "8\000B\000I\000M\000#" },
    { "8BIMTEXT", 0, "8BIM#" },
    { "8BIM", 0, "8BIM" },
    { "BMP", 0, "BA" },
    { "BMP", 0, "BM" },
    { "BMP", 0, "CI" },
    { "BMP", 0, "CP" },
    { "BMP", 0, "IC" },
    { "PICT", 0, "PICT" },
    { "BMP", 0, "PI" },
    { "CALS", 21, "version: MIL-STD-1840" },
    { "CALS", 0, "srcdocid:" },
    { "CALS", 9, "srcdocid:" },
    { "CALS", 8, "rorient:" },
    { "CGM", 0, "BEGMF" },
    { "CIN", 0, "\200\052\137\327" },
    { "CRW", 0, "II\x1a\x00\x00\x00HEAPCCDR" },
    { "DCM", 128, "DICM" },
    { "DCX", 0, "\261\150\336\72" },
    { "DIB", 0, "\050\000" },
    { "DDS", 0, "DDS " },
    { "DJVU", 0, "AT&TFORM" },
    { "DOT", 0, "digraph" },
    { "DPX", 0, "SDPX" },
    { "DPX", 0, "XPDS" },
    { "EMF", 40, "\040\105\115\106\000\000\001\000" },
    { "EPT", 0, "\305\320\323\306" },
    { "EXR", 0, "\166\057\061\001" },
    { "FAX", 0, "DFAX" },
    { "FIG", 0, "#FIG" },
    { "FITS", 0, "IT0" },
    { "FITS", 0, "SIMPLE" },
    { "FPX", 0, "\320\317\021\340" },
    { "GIF", 0, "GIF8" },
    { "GPLT", 0, "#!/usr/local/bin/gnuplot" },
    { "HDF", 1, "HDF" },
    { "HDR", 0, "#?RADIANCE" },
    { "HDR", 0, "#?RGBE" },
    { "HPGL", 0, "IN;" },
    { "HTML", 1, "HTML" },
    { "HTML", 1, "html" },
    { "ILBM", 8, "ILBM" },
    { "IPTCWTEXT", 0, "\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000" },
    { "IPTCTEXT", 0, "2#0=\042&#0;&#2;\042" },
    { "IPTC", 0, "\034\002" },
    { "JNG", 0, "\213JNG\r\n\032\n" },
    { "JPEG", 0, "\377\330\377" },
    { "JPC", 0, "\377\117" },
    { "JP2", 4, "\152\120\040\040\015" },
    { "MAT", 0, "MATLAB 5.0 MAT-file," },
    { "MIFF", 0, "Id=ImageMagick" },
    { "MIFF", 0, "id=ImageMagick" },
    { "MNG", 0, "\212MNG\r\n\032\n" },
    { "MPC", 0, "id=MagickCache" },
    { "MPEG", 0, "\000\000\001\263" },
    { "MRW", 0, "\x00MRM" },
    { "MVG", 0, "push graphic-context" },
    { "ORF", 0, "IIRO\x08\x00\x00\x00" },
    { "PCD", 2048, "PCD_" },
    { "PCL", 0, "\033E\033" },
    { "PCX", 0, "\012\002" },
    { "PCX", 0, "\012\005" },
    { "PDB", 60, "vIMGView" },
    { "PDF", 0, "%PDF-" },
    { "PES", 0, "#PES" },
    { "PFA", 0, "%!PS-AdobeFont-1.0" },
    { "PFB", 6, "%!PS-AdobeFont-1.0" },
    { "PGX", 0, "\050\107\020\115\046" },
    { "PICT", 522, "\000\021\002\377\014\000" },
    { "PNG", 0, "\211PNG\r\n\032\n" },
    { "PBM", 0, "P1" },
    { "PGM", 0, "P2" },
    { "PPM", 0, "P3" },
    { "PBM", 0, "P4" },
    { "PGM", 0, "P5" },
    { "PPM", 0, "P6" },
    { "PAM", 0, "P7" },
    { "PFM", 0, "PF" },
    { "PFM", 0, "Pf" },
    { "PS", 0, "%!" },
    { "PS", 0, "\004%!" },
    { "PS", 0, "\305\320\323\306" },
    { "PSB", 0, "8BPB" },
    { "PSD", 0, "8BPS" },
    { "PWP", 0, "SFW95" },
    { "RAF", 0, "FUJIFILMCCD-RAW " },
    { "RLE", 0, "\122\314" },
    { "SCT", 0, "CT" },
    { "SFW", 0, "SFW94" },
    { "SGI", 0, "\001\332" },
    { "SUN", 0, "\131\246\152\225" },
    { "SVG", 1, "?XML" },                       
    { "SVG", 1, "?xml" },
    { "TIFF", 0, "\115\115\000\052" },
    { "TIFF", 0, "\111\111\052\000" },
    { "TIFF64", 0, "\115\115\000\053\000\010\000\000" },
    { "TIFF64", 0, "\111\111\053\000\010\000\000\000" },
    { "TTF", 0, "\000\001\000\000\000" },
    { "TXT", 0, "# ImageMagick pixel enumeration:" },
    { "VICAR", 0, "LBLSIZE" },
    { "VICAR", 0, "NJPL1I" },
    { "VIFF", 0, "\253\001" },
    { "WEBP", 8, "WEBP" },
    { "WMF", 0, "\327\315\306\232" },
    { "WMF", 0, "\001\000\011\000" },
    { "WPG", 0, "\377WPC" },
    { "XBM", 0, "#define" },
    { "XCF", 0, "gimp xcf" },
    { "XEF", 0, "FOVb" },
    { "XPM", 1, "* XPM *" },
    { "XWD", 4, "\007\000\000" },
    { "XWD", 5, "\000\000\007" }
 };