<?php

//namespace gifCreator;

/**
* Create an animated GIF from multiple images
*/
class gifcreator
{
/**
* @var string The gif string source (old: this->GIF)
*/
private $gif; /**
* @var string Encoder version (old: this->VER)
*/
private $version; /**
* @var boolean Check the image is build or not (old: this->IMG)
*/
private $imgBuilt; /**
* @var array Frames string sources (old: this->BUF)
*/
private $frameSources; /**
* @var integer Gif loop (old: this->LOP)
*/
private $loop; /**
* @var integer Gif dis (old: this->DIS)
*/
private $dis; /**
* @var integer Gif color (old: this->COL)
*/
private $colour; /**
* @var array (old: this->ERR)
*/
private $errors; // Methods
// =================================================================================== /**
* Constructor
*/
public function __construct()
{
$this->reset(); // Static data
$this->version = 'GifCreator: Under development';
$this->errors = array(
'ERR00' => 'Does not supported function for only one image.',
'ERR01' => 'Source is not a GIF image.',
'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.',
'ERR03' => 'Does not make animation from animated GIF source.',
);
} /**
* Create the GIF string (old: GIFEncoder)
*
* @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs
* @param array $durations An array containing the duration of each frame
* @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop)
*
* @return string The GIF string source
*/
public function create($frames = array(), $durations = array(), $loop = 0)
{
if (!is_array($frames) && !is_array($durations)) { throw new \Exception($this->version.': '.$this->errors['ERR00']);
} $this->loop = ($loop > -1) ? $loop : 0;
$this->dis = 2; for ($i = 0; $i < count($frames); $i++) { if (is_resource($frames[$i])) { // Resource var $resourceImg = $frames[$i]; ob_start();
imagegif($frames[$i]);
$this->frameSources[] = ob_get_contents();
ob_end_clean(); } elseif (is_string($frames[$i])) { // File path or URL or Binary source code if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path $frames[$i] = file_get_contents($frames[$i]);
} $resourceImg = imagecreatefromstring($frames[$i]); ob_start();
imagegif($resourceImg);
$this->frameSources[] = ob_get_contents();
ob_end_clean(); } else { // Fail throw new \Exception($this->version.': '.$this->errors['ERR02']);
} if ($i == 0) { $colour = imagecolortransparent($resourceImg);
} if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr($this->frameSources[$i], 0, 6) != 'GIF89a') { throw new \Exception($this->version.': '.$i.' '.$this->errors['ERR01']);
} for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))), $k = TRUE; $k; $j++) { switch ($this->frameSources[$i] { $j }) { case '!': if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') { throw new \Exception($this->version.': '.$this->errors['ERR03'].' ('.($i + 1).' source).');
} break; case ';': $k = false;
break;
}
} unset($resourceImg);
} if (isset($colour)) { $this->colour = $colour; } else { $red = $green = $blue = 0;
$this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1;
} $this->gifAddHeader();
//d(count($this->frameSources));
for ($i = 0; $i < count($this->frameSources); $i++) {
$this->addGifFrames($i, $durations[$i]);
} $this->gifAddFooter(); return $this->gif;
} // Internals
// =================================================================================== /**
* Add the header gif string in its source (old: GIFAddHeader)
*/
public function gifAddHeader()
{
$cmap = 0; if (ord($this->frameSources[0] { 10 }) & 0x80) { $cmap = 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07)); $this->gif .= substr($this->frameSources[0], 6, 7);
$this->gif .= substr($this->frameSources[0], 13, $cmap);
$this->gif .= "!\377\13NETSCAPE2.0\3\1".$this->encodeAsciiToChar($this->loop)."\0";
}
} /**
* Add the frame sources to the GIF string (old: GIFAddFrames)
*
* @param integer $i
* @param integer $d
*/
public function addGifFrames($i, $d)
{ $Locals_str = 13 + 3 * (2 << (ord($this->frameSources[ $i ] { 10 }) & 0x07)); $Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1;
$Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end); $Global_len = 2 << (ord($this->frameSources[0 ] { 10 }) & 0x07);
$Locals_len = 2 << (ord($this->frameSources[$i] { 10 }) & 0x07); $Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07)));
$Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))); $Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 0).chr(($d >> 0 ) & 0xFF).chr(($d >> 8) & 0xFF)."\x0\x0"; if ($this->colour > -1 && ord($this->frameSources[$i] { 10 }) & 0x80) { for ($j = 0; $j < (2 << (ord($this->frameSources[$i] { 10 } ) & 0x07)); $j++) { if (ord($Locals_rgb { 3 * $j + 0 }) == (($this->colour >> 16) & 0xFF) &&
ord($Locals_rgb { 3 * $j + 1 }) == (($this->colour >> 8) & 0xFF) &&
ord($Locals_rgb { 3 * $j + 2 }) == (($this->colour >> 0) & 0xFF)
) {
$Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 1).chr(($d >> 0) & 0xFF).chr(($d >> 8) & 0xFF).chr($j)."\x0";
break;
}
}
} switch ($Locals_tmp { 0 }) { case '!': $Locals_img = substr($Locals_tmp, 8, 10);
$Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18); break; case ',': $Locals_img = substr($Locals_tmp, 0, 10);
$Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10); break;
} if (ord($this->frameSources[$i] { 10 }) & 0x80 && $this->imgBuilt) { if ($Global_len == $Locals_len) { if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) { $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp; } else { $byte = ord($Locals_img { 9 });
$byte |= 0x80;
$byte &= 0xF8;
$byte |= (ord($this->frameSources[0] { 10 }) & 0x07);
$Locals_img { 9 } = chr($byte);
$this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
} } else { $byte = ord($Locals_img { 9 });
$byte |= 0x80;
$byte &= 0xF8;
$byte |= (ord($this->frameSources[$i] { 10 }) & 0x07);
$Locals_img { 9 } = chr($byte);
$this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
} } else { $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp;
} $this->imgBuilt = true;
} /**
* Add the gif string footer char (old: GIFAddFooter)
*/
public function gifAddFooter()
{
$this->gif .= ';';
} /**
* Compare two block and return the version (old: GIFBlockCompare)
*
* @param string $globalBlock
* @param string $localBlock
* @param integer $length
*
* @return integer
*/
public function gifBlockCompare($globalBlock, $localBlock, $length)
{
for ($i = 0; $i < $length; $i++) { if ($globalBlock { 3 * $i + 0 } != $localBlock { 3 * $i + 0 } ||
$globalBlock { 3 * $i + 1 } != $localBlock { 3 * $i + 1 } ||
$globalBlock { 3 * $i + 2 } != $localBlock { 3 * $i + 2 }) { return 0;
}
} return 1;
} /**
* Encode an ASCII char into a string char (old: GIFWord)
*
* $param integer $char ASCII char
*
* @return string
*/
public function encodeAsciiToChar($char)
{
return (chr($char & 0xFF).chr(($char >> 8) & 0xFF));
} /**
* Reset and clean the current object
*/
public function reset()
{
$this->frameSources;
$this->gif = 'GIF89a'; // the GIF header
$this->imgBuilt = false;
$this->loop = 0;
$this->dis = 2;
$this->colour = -1;
} // Getter / Setter
// =================================================================================== /**
* Get the final GIF image string (old: GetAnimation)
*
* @return string
*/
public function getGif()
{
return $this->gif;
}
} //图片资源写入数组,支持如下图片资源。
$frames = array(
"http://pic27.nipic.com/20130313/9252150_092049419327_2.jpg",
"http://pic27.nipic.com/20130324/9252150_152129329000_2.jpg",
"http://pic44.nipic.com/20140723/18505720_094503373000_2.jpg",
"http://pic18.nipic.com/20120103/8993051_170340691334_2.jpg"
); // 设置图片转换快慢,数值越小越快,数组个数和frames对应。
$durations = array(40, 80, 40, 20); $gc = new GifCreator();
$gifBinary = $gc->create($frames, $durations, 0); file_put_contents('./ceshi.gif',$gifBinary);

php 生成gif 动图,可控制每张图时间的更多相关文章

  1. android安卓生成密钥keystore(命令控制)

    android安卓生成密钥keystore(命令控制) • 配置JDK 详细教程 https://blog.csdn.net/u012934325/article/details/73441617/ ...

  2. S​Q​L​_​S​e​r​v​e​r​_​2​0​0​8​定​期​自​动​备​份​详​细​图​解

    S​Q​L​_​S​e​r​v​e​r​_​2​0​0​8​定​期​自​动​备​份​详​细​图​解 设置自动数据库的定期备份计划. http://wenku.baidu.com/link?url=Tu ...

  3. EA逆向生成数据库E-R图(mysql数据库-->ER图)

    [1]选择 工具-->ODBC-Data-Sources [2]ODBC数据源管理器  ,点击添加 [3]选择一个mysql驱动  ,点击MySQL ODBC 5.1 Driver(其它同理), ...

  4. Shader中贴图知识汇总: 漫反射贴图、凹凸贴图、高光贴图、 AO贴图、环境贴图、 光照纹理及细节贴图

    原文过于冗余,精读后做了部分简化与测试实践,原文地址:http://www.j2megame.com/html/xwzx/ty/2571.html   http://www.cnblogs.com/z ...

  5. PS-前端切图教程(切jpg图和切png图)

    微微一运功,把家底都抖出来了. 不过,作为一个设计出身的前端来说,摸ps就和摸键盘一样了 所以可能教程中还是有没用过ps的人看不懂的地方, 欢迎加群讨论:613512106... ---------- ...

  6. 【UML 建模】UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战

    发现个好东西思维导图, 最近开始用MindManager整理博客 . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/deta ...

  7. (转)Unity3D 游戏贴图(法线贴图,漫反射贴图,高光贴图)

    原帖网址http://www.u3dpro.com/read.php?tid=207  感谢jdk900网友的辛苦编写 我们都知道,一个三维场景的画面的好坏,百分之四十取决于模型,百分之六十取决于贴图 ...

  8. UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战

    发现个好东西思维导图, 最近开始用MindManager整理博客 . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/deta ...

  9. D3.js系列——布局:弦图和集群图/树状图

    一.弦图 1.弦图是什么 弦图(Chord),主要用于表示两个节点之间的联系的图表.两点之间的连线,表示谁和谁具有联系. 2.数据 初始数据为: var city_name = [ "北京& ...

随机推荐

  1. 汉化Git Gui

    先来一个图: 其实使用自带的图形化操作git还是很方便的,但是英文界面还是让相当一部分小伙伴不太舒服,比如我哈. 汉化包地址:链接: https://pan.baidu.com/s/1qQtBUsf1 ...

  2. 帝国cms 批量替换语句

    UPDATE www_92game_net_cnys_ecms_caipu SET titlepic=REPLACE(titlepic,'http://file.92game.net', '') ; ...

  3. go timer定时器 WaitGroup用法

    参考文章: timer定时器: https://www.cnblogs.com/oxspirt/p/7107312.html WaitGroup用法: https://studygolang.com/ ...

  4. OS填空题练习

    1.操作系统的基本特征:并发性:共享性:虚拟性:异步性. 2.操作系统的设计目标:方便性:有效性:可扩充性:开放性. 3.操作系统的主要功能:处理机管理:存储器管理:设备管理:文件管理:用户接口. 4 ...

  5. rsyslog服务日志报错分析1

    客户问题: 最近对服务器进行日志检查时,发现部分主机的rsyslog服务状态有报错,报错详情如下 排查过程: 1.从报错截图来看,报错主要发生在文件'/usr/lib64/rsyslog/omazur ...

  6. [转帖]Cacls和ICacls

    Cacls和ICacls https://www.cnblogs.com/Aley/p/11089538.html Need Study 解释:  Cacls:显示或修改文件的访问控制列表(ACL) ...

  7. 【C++札记】标准模板库string

    介绍 c++中字符串string对象属于一个类,内置了很多实用的成员函数,操作简单,方便更直观. 命名空间为std,所属头文件<string> 注意:不是<string.h>. ...

  8. Python复习笔记02

    语句表达式: 在Python中支持遍历循环的对象:可迭代器对象,支持迭代协议的对象 比如列表list没有迭代功能只是可迭代对象 迭代:迭代协议 --> 例:f.__next__() 属于f的迭代 ...

  9. mac OS 安装qt环境

    先安装xcode,然后从官网下载dmg安装包安装即可,这里主要出现一个问题就是创建的工程没法编译,提示没有构建包(kit) 要安装command line tool才行. 在命令行中输入: xcode ...

  10. hdu 6205 card card card 尺取法

    card card card Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...