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" } };