Getting the Mimetype of an Image with PHP

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�\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" }
};
« Disqus 2012 Default Sort Order FixFix Linux Users Home Permissions with a Cron Job »
Comments