<?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. 基于Visual Studio Code搭建Vue开发环境

    安装node.js最新版 这里安装的是8.11.4版   image.png 更新npm至最新版 安装node.js后, npm默认版本为: 6.1.0   image.png 使用npm insta ...

  2. Docker 跨主机网络 overlay(十六)

    目录 一.跨主机网络概述 二.准备 overlay 环境 1.环境描述 2.创建 consul 3.修改 docker 配置文件 4.准备就绪 三.创建 overlay 网络 1.在 host1 中创 ...

  3. php 因循环数据 赋值变量 占用内存太大 提示错误

    Fatal error: Allowed memory size of 134217728 bytes exhausted 网上很多解决方法:就简单记录下 一个csv导入功能 由于数据太多 占用内存太 ...

  4. 最新 游族网络java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.游族网络等10家互联网公司的校招Offer,因为某些自身原因最终选择了游族网络.6.7月主要是做系统复习.项目复盘.Leet ...

  5. Shiro认证、角色、权限

    Apache Shiro 是 Java 的一个安全框架.Shiro 可以帮助我们完成:认证.授权.加密.会话管理.与 Web 集成.缓存等. Shiro的内置Realm:IniRealm和JdbcRe ...

  6. JRE和JDK的作用和区别

    JVM(Java  Virtual Machine)是一个虚拟的用于执行bytecode字节码的“虚拟计算机”JRE(Java   Runtime  Environment):Java 虚拟机.库函数 ...

  7. VisualStudioCode网页开发常用插件

    VS下载链接 提取码:usx8 VsCode扩展功能强大,在于他可以安装各种各样的插件来辅助开发.下面是我初学前端时常用的vscode开发插件 Chinese 汉化 Beautify 格式化javas ...

  8. Java基础---Java方法

    基本方法的定义: public static void 方法名称() { 方法体 } 方法名称的命名规则和变量一样,使用小驼峰. 方法体:也就是大括号当中可以包含任意条语句. 注意事项: 1. 方法定 ...

  9. POJ 2299-Ultra-QuickSort-线段树的两种建树方式

    此题有两种建树方式! Description In this problem, you have to analyze a particular sorting algorithm. The algo ...

  10. go hello world第一个程序

    main 函数所在的包名必须使用main import "fmt"  导入包fmt  fmt包包含了Println方法的定义 func main() 程序运行入口方法和c语言相似 ...