PHP的GD库,没有办法直接判断一张gif图片是否是动态的,其gif相关的函数操作的都是动态gif图片的第一帧。
imagecreatefromgif
函数的文档中提及了动态gif的判断,即数"frame header"的个数。
//an animated gif contains multiple "frames", with each frame having a //header made up of: // * a static 4-byte sequence (\x00\x21\xF9\x04) // * 4 variable bytes // * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)
下面的方法来自PHP文档,分区块读取数据,正则表达式判断。
function is_animated_gif($filename){ if(!($fh = @fopen($filename, 'rb'))) return false; $count = 0; while(!feof($fh) && $count < 2) { $chunk = fread($fh, 1024 * 100); //read 100kb at a time $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches); } fclose($fh); return $count > 1; }
但是缺点是不能解决frame header跨区块的情况,正则表达式的速度也略慢一些。
下面是自己的修正实现
function is_animated_gif($filename){ if(!($fh = @fopen($filename, 'rb'))) return false; $count = 0; while(!feof($fh) && $count < 2) { $chunk = fread($fh, 1024 * 100 + 9); //read 100kb at a time $size = strlen($chunk); $offset = 0; while($count<2){ $pos = strpos($chunk, "\x00\x21\xF9\x04", $offset); if(false===$pos){ if(!feof($fh)) fseek($fh, -3, SEEK_CUR); // next chunk break; }else{ if($pos<($size-9)){ if( substr_compare($chunk, "\x00\x2c", $pos+8,2)==0 || substr_compare($chunk, "\x00\x21", $pos+8,2)==0 ) { $count++; $offset = $pos+10; }else{ $offset = $pos+4; } }else{ fseek($fh, strlen($chunk)-$pos-1, SEEK_CUR); // next chunk break; } } } } fclose($fh); return $count > 1?1:0; }