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