完美实现GIF动画缩略图的php代码


Posted in PHP onJanuary 02, 2011

下面通过一个取自CS警匪游戏的GIF动画来说明问题:

完美实现GIF动画缩略图的php代码

GIF动画图片:old.gif

为了让问题更加清晰,我们先还原动画各帧:

选择一:用PHP中的Imagick模块:

<?php 
$image = new Imagick('old.gif'); 
$i = 0; 
foreach ($image as $frame) { 
$frame->writeImage('old_' . $i++ . '.gif'); 
} 
?>

选择二:用ImageMagick提供的convert命令:
shell> convert old.gif old_%d.gif

结果得到GIF动画各帧示意图如下所示:

完美实现GIF动画缩略图的php代码

GIF动画各帧示意图

可以明显的看到,GIF动画为了压缩,会以第一帧为模板,其余各帧按照适当的偏移量依次累加,并只保留不同的像素,结果是导致各帧尺寸不尽相同,为缩略图造成障碍。

下面看看如何用PHP中的Imagick模块来完美实现GIF动画缩略图:

<?php 
$image = new Imagick('old.gif'); 
$image = $image->coalesceImages(); 
foreach ($image as $frame) { 
$frame->thumbnailImage(50, 50); 
} 
$image = $image->optimizeImageLayers(); 
$image->writeImages('new.gif', true); 
?>

代码里最关键的是coalesceimages方法,它确保各帧尺寸一致,用手册里的话来说就是:

Composites a set of images while respecting any page offsets and disposal methods. GIF, MIFF, and MNG animation sequences typically start with an image background and each subsequent image varies in size and offset. Returns a new Imagick object where each image in the sequence is the same size as the first and composited with the next image in the sequence.

同时要注意optimizeImageLayers方法,它删除重复像素内容,用手册里的话来说就是:

Compares each image the GIF disposed forms of the previous image in the sequence. From this it attempts to select the smallest cropped image to replace each frame, while preserving the results of the animation.

BTW:如果要求更完美一点,可以使用quantizeImages方法进一步压缩。

注意:不管是coalesceimages,还是optimizeImageLayers,都是返回新的Imagick对象!

如果你更习惯操作shell的话,那么可以这样实现GIF动画缩略图:

shell> convert old.gif -coalesce -thumbnail 50x50 -layers optimize new.gif

生成的new.gif如下:

 

完美实现GIF动画缩略图的php代码

new.gif

有个细节问题:convert版本会比php版本小一些,这是API实现不一致所致。

另外,如果缩略图尺寸不符合原图比例,为了避免变形,还要考虑裁剪或者是补白,由于本文主要讨论GIF动画缩略图的特殊性,就不再继续讨论这些问题了,有兴趣的自己搞定吧。

PHP 相关文章推荐
一个ubbcode的函数,速度很快.
Oct 09 PHP
用mysql内存表来代替php session的类
Feb 01 PHP
PHP json格式和js json格式 js跨域调用实现代码
Sep 08 PHP
PHP不用递归遍历目录下所有文件的代码
Jul 04 PHP
WordPress中访客登陆实现邮件提醒的PHP脚本实例分享
Dec 14 PHP
Composer设置忽略版本匹配的方法
Apr 27 PHP
php实现36进制与10进制转换功能示例
Jan 10 PHP
PHP从数组中删除元素的四种方法实例
May 12 PHP
php使用curl实现ftp文件下载功能
May 16 PHP
php检测mysql表是否存在的方法小结
Jul 20 PHP
PHP 传输会话curl函数的实例详解
Sep 12 PHP
PHP文件管理之实现网盘及压缩包的功能操作
Sep 20 PHP
php实现无限级分类实现代码(递归方法)
Jan 01 #PHP
php下尝试使用GraphicsMagick的缩略图功能
Jan 01 #PHP
PHP读取XML值的代码(推荐)
Jan 01 #PHP
PHP中simplexml_load_string函数使用说明
Jan 01 #PHP
php xml 入门学习资料
Jan 01 #PHP
PHP+SQL 注入攻击的技术实现以及预防办法
Dec 29 #PHP
解决PHP在DOS命令行下却无法链接MySQL的技术笔记
Dec 29 #PHP
You might like
session在php5.3中的变化 session_is_registered() is deprecated in
2013/11/12 PHP
php判断ip黑名单程序代码实例
2014/02/24 PHP
thinkPHP实现签到功能的方法
2017/03/15 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
出现“不能执行已释放的Script代码”错误的原因及解决办法
2007/08/29 Javascript
JQuery 获得绝对,相对位置的坐标方法
2010/02/09 Javascript
JSQL SQLProxy 的 php 版本代码
2010/05/05 Javascript
基于jquery的让textarea自适应高度的插件
2010/08/03 Javascript
Javascript中valueOf与toString区别浅析
2013/03/19 Javascript
两个多选select(multiple左右)添加、删除选项和取值实例
2014/05/12 Javascript
javascript中声明函数的方法及调用函数的返回值
2014/07/22 Javascript
用javascript实现自动输出网页文本
2015/07/30 Javascript
QQ登录背景闪动效果附效果演示源码下载
2015/09/22 Javascript
node.js回调函数之阻塞调用与非阻塞调用
2015/11/13 Javascript
使用jQuery判断浏览器滚动条位置的方法
2016/05/30 Javascript
全面解析JavaScript中“&amp;&amp;”和“||”操作符(总结篇)
2016/07/18 Javascript
jquery仿京东侧边栏导航效果
2017/03/02 Javascript
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
2018/03/09 Javascript
微信小程序实现带缩略图轮播效果
2018/11/04 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
Vue如何获取数据列表展示
2019/12/11 Javascript
vue项目中使用bpmn为节点添加颜色的方法
2020/04/30 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
2020/08/17 Javascript
Openlayers实现点闪烁扩散效果
2020/09/24 Javascript
全面了解python字符串和字典
2016/07/07 Python
Python HTTP客户端自定义Cookie实现实例
2017/04/28 Python
终端命令查看TensorFlow版本号及路径的方法
2018/06/13 Python
详解Django中间件的5种自定义方法
2018/07/26 Python
使用Python实现跳一跳自动跳跃功能
2019/07/10 Python
wxpython实现按钮切换界面的方法
2019/11/19 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
一篇文章教你用python画动态爱心表白
2020/11/22 Python
给校长的建议书500字
2014/05/15 职场文书
长城英文导游词
2015/01/30 职场文书
英文诗歌翻译方法(赏析)
2019/08/16 职场文书
Python数据处理的三个实用技巧分享
2022/04/01 Python