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

最新文章

  1. mysql 查询去重 distinct
  2. [python] os.path说明
  3. AngularJS in Action读书笔记3——走近Services
  4. 孙鑫MFC学习笔记14:网络编程
  5. SQL中的取整函数FLOOR、ROUND、CEIL、TRUNC、SIGN
  6. css强制换行和超出隐藏实现
  7. 关于Activity销毁,而绘制UI的子线程未销毁出现的问题
  8. MySQL 用户管理&mdash;&mdash;权限表
  9. js 实现win7任务栏拖动效果
  10. bison实例
  11. 【开发技术】java+mysql 更改表字段的步骤
  12. Android类似Periscope点赞效果
  13. deepin 15.8桌面系统
  14. Django通用视图APIView和视图集ViewSet的介绍和使用
  15. mybatis+oracle实现简单的模糊查询
  16. Mac 日常使用tips
  17. 【转载】C#调用C++ DLL
  18. php multicast多播实现详解
  19. Daily Scrum (2015/10/22)
  20. ref:下一个项目为什么要用 SLF4J

热门文章

  1. 【c# 学习笔记】面向对象编程的应用
  2. CenOS 7 java链接redis数据库
  3. 阿里云主机如何设置swap
  4. hdu 1209 Clock
  5. html5 table的表头固定的HTML代码
  6. PPT 中用 LaTeX 插入公式、PowerPoint 中用 LaTeX 插入公式(4)
  7. Prime Time UVA - 10200(精度处理,素数判定)
  8. 某 游戏公司 php 面试题
  9. pandas之聚合运算
  10. Luogu4022 CTSC2012熟悉的文章(广义后缀自动机+二分答案+动态规划+单调队列)