判断Gif图片是否是动态GIF (Animated Gif)

风行水上 @ 2014-12-25 17:24:21
标签:

    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;
    }
    
    标签:

      分享到:
      comments powered by Disqus

      28/30ms