php编译gd支持gif,我可以使用php和gd检测GIF动画吗?

我可以使用php和gd检测GIF动画吗?

我目前在使用GD调整图片大小时遇到一些问题。

一切正常,直到我想调整动画gif的大小为止,它会在黑色背景上提供第一帧。

我尝试使用getimagesize,但这只给了我尺寸,没有任何东西可以区分任何gif和动画。

动画gif不需要实际调整大小,只是能够跳过它们就足以满足我们的目的。

有什么线索吗?

PS。 我无权使用imagemagick。

亲切的问候,

克里斯

Kris asked 2020-08-02T14:23:13Z

6个解决方案

38 votes

在寻找相同问题的解决方案时,我注意到php.net站点对Davide和Kris所指代的代码进行了跟踪,但是据作者说,它占用的内存较少,并且可能占用的磁盘较少 。

我会在这里复制它,因为它可能很有趣。

来源:[http://www.php.net/manual/en/function.imagecreatefromgif.php#88005]

function is_ani($filename) {

if(!($fh = @fopen($filename, 'rb')))

return false;

$count = 0;

//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)

// We read through the file til we reach the end of the file, or we've found

// at least 2 frame headers

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;

}

Martijn Heemels answered 2020-08-02T14:24:01Z

18 votes

imagecreatefromgif函数的PHP手册页上有简短的代码片段,应该是您所需要的:

imagecreatefromgif评论#59787由ZeBadger

Davide Gualano answered 2020-08-02T14:23:32Z

7 votes

这是工作功能:

/**

* Thanks to ZeBadger for original example, and Davide Gualano for pointing me to it

* Original at http://it.php.net/manual/en/function.imagecreatefromgif.php#59787

**/

function is_animated_gif( $filename )

{

$raw = file_get_contents( $filename );

$offset = 0;

$frames = 0;

while ($frames < 2)

{

$where1 = strpos($raw, "\x00\x21\xF9\x04", $offset);

if ( $where1 === false )

{

break;

}

else

{

$offset = $where1 + 1;

$where2 = strpos( $raw, "\x00\x2C", $offset );

if ( $where2 === false )

{

break;

}

else

{

if ( $where1 + 8 == $where2 )

{

$frames ++;

}

$offset = $where2 + 1;

}

}

}

return $frames > 1;

}

Kris answered 2020-08-02T14:24:21Z

2 votes

如果给定文件太大,则用file_get_contents读取整个文件可能会占用太多内存。 我已经重构了前面给出的函数,该函数读取足够的字节以检查帧并在找到至少2个帧后立即返回。

/**

* Detects animated GIF from given file pointer resource or filename.

*

* @param resource|string $file File pointer resource or filename

* @return bool

*/

function is_animated_gif($file)

{

$fp = null;

if (is_string($file)) {

$fp = fopen($file, "rb");

} else {

$fp = $file;

/* Make sure that we are at the beginning of the file */

fseek($fp, 0);

}

if (fread($fp, 3) !== "GIF") {

fclose($fp);

return false;

}

$frames = 0;

while (!feof($fp) && $frames < 2) {

if (fread($fp, 1) === "\x00") {

/* Some of the animated GIFs do not contain graphic control extension (starts with 21 f9) */

if (fread($fp, 1) === "\x2c" || fread($fp, 2) === "\x21\xf9") {

$frames++;

}

}

}

fclose($fp);

return $frames > 1;

}

hdogan answered 2020-08-02T14:24:41Z

0 votes

这是当前最高投票答案的改进,但是我没有足够的声誉来发表评论。 该答案的问题在于它以100Kb的块读取文件,并且帧尾标记可能会分成2个块。 一个解决方法是将上一帧的最后20b添加到下一帧:

function is_ani($filename) {

if(!($fh = @fopen($filename, 'rb')))

return false;

$count = 0;

//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 ?)

// We read through the file til we reach the end of the file, or we've found

// at least 2 frame headers

$chunk = false;

while(!feof($fh) && $count < 2) {

//add the last 20 characters from the previous string, to make sure the searched pattern is not split.

$chunk = ($chunk ? substr($chunk, -20) : "") . 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;

}

Simon - ShortPixel answered 2020-08-02T14:25:02Z

-1 votes

动画GIF必须具有以下字符串

"\x21\xFF\x0B\x4E\x45\x54\x53\x43\x41\x50\x45\x32\x2E\x30"

我已经对一些动画gif进行了测试,该字符串似乎位于文件的位置781(可通过file_get_contents和strpos找到)

user2731504 answered 2020-08-02T14:25:26Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值