Commit 04e4b3bf072a3b6b682208e98f9f661638e3a372
1 parent
6527d3d0
Exists in
master
and in
7 other branches
Ferramenta de Animacao no formato gif
Showing
4 changed files
with
617 additions
and
0 deletions
Show diff stats
admin/admin.db
No preview for this file type
| ... | ... | @@ -0,0 +1,192 @@ |
| 1 | +<?php | |
| 2 | +//$tema - nome do mapfile | |
| 3 | +//$colunat - coluna que contem os periodos | |
| 4 | +//$tempo - tempo entre os frames | |
| 5 | +//$w | |
| 6 | +//$h | |
| 7 | +//$cache | |
| 8 | +//$mapext | |
| 9 | +//http://localhost/i3geo/ferramentas/animagif/exec.php?tema=_llocali&colunat=ANOCRIA&w=500&h=500&mapext=-72%20-33%20-32%204 | |
| 10 | +include("../../ms_configura.php"); | |
| 11 | +include("../../classesphp/funcoes_gerais.php"); | |
| 12 | +include("../../classesphp/pega_variaveis.php"); | |
| 13 | +include("../../classesphp/carrega_ext.php"); | |
| 14 | +$nometemp = nomeRandomico(); | |
| 15 | +$arqtemp = $dir_tmp."/".$nometemp; | |
| 16 | +// | |
| 17 | +//carrega o phpmapscript | |
| 18 | +// | |
| 19 | +if (!function_exists('ms_GetVersion')) | |
| 20 | +{ | |
| 21 | + if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')) | |
| 22 | + { | |
| 23 | + if(!@dl('php_mapscript_48.dll')) | |
| 24 | + dl('php_mapscript.dll'); | |
| 25 | + } | |
| 26 | + else | |
| 27 | + {dl('php_mapscript.so'); | |
| 28 | + } | |
| 29 | +} | |
| 30 | +$versao = versao(); | |
| 31 | +$versao = $versao["principal"]; | |
| 32 | + | |
| 33 | +//cria um mapa temporario | |
| 34 | +if($base == "" or !isset($base)){ | |
| 35 | + $base = ""; | |
| 36 | + if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')){ | |
| 37 | + $base = $locaplic."/aplicmap/geral1windowsv".$versao.".map"; | |
| 38 | + } | |
| 39 | + else{ | |
| 40 | + if($base == "" && file_exists('/var/www/i3geo/aplicmap/geral1debianv'.$versao.'.map')){ | |
| 41 | + $base = "/var/www/i3geo/aplicmap/geral1debianv".$versao.".map"; | |
| 42 | + } | |
| 43 | + if($base == "" && file_exists('/var/www/html/i3geo/aplicmap/geral1fedorav'.$versao.'.map')){ | |
| 44 | + $base = "/var/www/html/i3geo/aplicmap/geral1fedorav".$versao.".map"; | |
| 45 | + } | |
| 46 | + if($base == "" && file_exists('/opt/www/html/i3geo/aplicmap/geral1fedorav'.$versao.'.map')){ | |
| 47 | + $base = "/opt/www/html/i3geo/aplicmap/geral1v".$versao.".map"; | |
| 48 | + } | |
| 49 | + if($base == ""){ | |
| 50 | + $base = $locaplic."/aplicmap/geral1v".$versao.".map"; | |
| 51 | + } | |
| 52 | + } | |
| 53 | +} | |
| 54 | +else{ | |
| 55 | + if(!file_exists($base)){ | |
| 56 | + $base = $locaplic."/aplicmap/".$base; | |
| 57 | + } | |
| 58 | +} | |
| 59 | +$mapa = ms_newMapObj($base); | |
| 60 | + | |
| 61 | +//remove as camadas do mapa base | |
| 62 | +$numlayers = $mapa->numlayers; | |
| 63 | +for ($i=0;$i < $numlayers;$i++){ | |
| 64 | + $layern = $mapa->getlayer($i); | |
| 65 | + if($layern->name != "copyright"){ | |
| 66 | + $layern->set("status",MS_DELETE); | |
| 67 | + } | |
| 68 | + else{ | |
| 69 | + $layern->set("status",MS_DEFAULT); | |
| 70 | + } | |
| 71 | +} | |
| 72 | +//ajusta o label | |
| 73 | +$l = $mapa->getlayerbyname("copyright"); | |
| 74 | +$classe = $l->getclass(0); | |
| 75 | +$label = $classe->getLabel(0); | |
| 76 | +$label->updatefromstring("LABEL TYPE TRUETYPE END"); | |
| 77 | +$label->set("font","arial"); | |
| 78 | +$label->set("size",15); | |
| 79 | +$label->updatefromstring("LABEL POSITION lr END"); | |
| 80 | +//$label->updatefromstring("LABEL OUTLINECOLOR 255 255 255 OUTLINEWIDTH 10 END"); | |
| 81 | +//$labels = new styleObj($classe); | |
| 82 | +$label->updatefromstring('LABEL STYLE GEOMTRANSFORM "labelpoly" COLOR 255 255 255 END END'); | |
| 83 | +// | |
| 84 | +$mapa->save($arqtemp.".map"); | |
| 85 | +//adiciona ao mapa base as camadas do mapfile indicado em $tema | |
| 86 | +$nmapa = ms_newMapObj($locaplic."/temas/".$tema.".map"); | |
| 87 | +$numlayers = $nmapa->numlayers; | |
| 88 | +for ($i=0;$i < $numlayers;$i++){ | |
| 89 | + $layern = $nmapa->getlayer($i); | |
| 90 | + $layern->set("status",MS_DEFAULT); | |
| 91 | + if (!empty($postgis_mapa)){ | |
| 92 | + if ($layern->connectiontype == MS_POSTGIS){ | |
| 93 | + $lcon = $layern->connection; | |
| 94 | + error_reporting(0); | |
| 95 | + if (($lcon == " ") || ($lcon == "") || (in_array($lcon,array_keys($postgis_mapa)))){ | |
| 96 | + if(($lcon == " ") || ($lcon == "")){ | |
| 97 | + $layern->set("connection",$postgis_mapa); | |
| 98 | + } | |
| 99 | + else{ | |
| 100 | + $layern->set("connection",$postgis_mapa[$lcon]); | |
| 101 | + } | |
| 102 | + } | |
| 103 | + } | |
| 104 | + } | |
| 105 | + autoClasses($layern,$nmapa); | |
| 106 | + cloneInlineSymbol($layern,$nmapa,$mapa); | |
| 107 | + ms_newLayerObj($mapa, $layern); | |
| 108 | +} | |
| 109 | +$mapa->save($arqtemp.".map"); | |
| 110 | +//aplica a extensao geografica | |
| 111 | +$layer = $mapa->getlayerbyname($tema); | |
| 112 | + | |
| 113 | +$extatual = $mapa->extent; | |
| 114 | +$ret = ""; | |
| 115 | +if(isset($mapext)){ | |
| 116 | + $ret = str_replace(","," ",$mapext); | |
| 117 | +} | |
| 118 | +else{ | |
| 119 | + $ret = $layer->getmetadata("extensao"); | |
| 120 | +} | |
| 121 | +if ($ret != ""){ | |
| 122 | + $ret = explode(" ",$ret); | |
| 123 | + $extatual->setextent($ret[0],$ret[1],$ret[2],$ret[3]); | |
| 124 | +} | |
| 125 | +$mapa->setsize($w,$h); | |
| 126 | +$sca = $mapa->scalebar; | |
| 127 | +$sca->set("status",MS_OFF); | |
| 128 | +$c = $mapa->imagecolor; | |
| 129 | +$c->setrgb(-1,-1,-1); | |
| 130 | +$o = $mapa->outputformat; | |
| 131 | +$o->set("imagemode",MS_IMAGEMODE_RGBA); | |
| 132 | +$o->set("transparent",MS_TRUE); | |
| 133 | +$mapa->save($arqtemp.".map"); | |
| 134 | +$mapa = ms_newMapObj($arqtemp.".map"); | |
| 135 | +if(validaAcessoTemas($arqtemp.".map",false) == true){ | |
| 136 | + echo "Existem temas restritos";exit; | |
| 137 | +} | |
| 138 | +//pega a lista de valores unicos da $colunat | |
| 139 | +include_once("../../classesphp/classe_atributos.php"); | |
| 140 | +$m = new Atributos($arqtemp.".map",$tema); | |
| 141 | +$lista = $m->listaRegistros($colunat,"mapa","sim",0,"","tudo","nao"); | |
| 142 | +$lista = $lista[1]["registros"]; | |
| 143 | +$listaunica = array(); | |
| 144 | +foreach($lista as $l){ | |
| 145 | + $v = $l["valores"][0]["valor"]; | |
| 146 | + if($v != ""){ | |
| 147 | + $listaunica[] = $v; | |
| 148 | + } | |
| 149 | +} | |
| 150 | +sort($listaunica); | |
| 151 | +//cria as imagens para cada periodo | |
| 152 | +$layer = $mapa->getlayerbyname($tema); | |
| 153 | + | |
| 154 | +$l = $mapa->getlayerbyname("copyright"); | |
| 155 | +$c = $l->getclass(0); | |
| 156 | +$label = $c->getLabel(0); | |
| 157 | + | |
| 158 | +$imagens = array(); | |
| 159 | +$duracao = array(); | |
| 160 | +$objImagem = ""; | |
| 161 | +//$listaunica = array($listaunica[1]); | |
| 162 | +foreach($listaunica as $d){ | |
| 163 | + $filtro = "(([$colunat] = $d))"; | |
| 164 | + $layer->setfilter($filtro); | |
| 165 | + $nomec = $arqtemp.$d.".png"; | |
| 166 | + | |
| 167 | + $s = "LABEL TEXT '".$d."' END"; | |
| 168 | + $label->updateFromString($s); | |
| 169 | + | |
| 170 | + if($objImagem == ""){ | |
| 171 | + $objImagem = $mapa->draw(); | |
| 172 | + $objImagem->saveImage($nomec); | |
| 173 | + } | |
| 174 | + else{ | |
| 175 | + $i = $mapa->draw(); | |
| 176 | + $objImagem->pasteImage($i,-1); | |
| 177 | + $objImagem->saveImage($nomec); | |
| 178 | + } | |
| 179 | + $imagens[] = $nomec; | |
| 180 | + $duracao[] = 40; | |
| 181 | +} | |
| 182 | +//junta as imagens no gif | |
| 183 | +include("../../pacotes/gifcreator/GifCreator.php"); | |
| 184 | +$gc = new GifCreator(); | |
| 185 | +$gc->create($imagens, $duracao, 1); | |
| 186 | +$gifBinary = $gc->getGif(); | |
| 187 | +//retorna o gif para o navegador | |
| 188 | +header('Content-type: image/gif'); | |
| 189 | +header('Content-Disposition: filename="butterfly.gif"'); | |
| 190 | +echo $gifBinary; | |
| 191 | +exit; | |
| 192 | +?> | |
| 0 | 193 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -0,0 +1,358 @@ |
| 1 | +<?php | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Create an animated GIF from multiple images | |
| 7 | + * | |
| 8 | + * @version 1.0 | |
| 9 | + * @link https://github.com/Sybio/GifCreator | |
| 10 | + * @author Sybio (Clément Guillemain / @Sybio01) | |
| 11 | + * @license http://opensource.org/licenses/gpl-license.php GNU Public License | |
| 12 | + * @copyright Clément Guillemain | |
| 13 | + */ | |
| 14 | +class GifCreator | |
| 15 | +{ | |
| 16 | + /** | |
| 17 | + * @var string The gif string source (old: this->GIF) | |
| 18 | + */ | |
| 19 | + private $gif; | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * @var string Encoder version (old: this->VER) | |
| 23 | + */ | |
| 24 | + private $version; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * @var boolean Check the image is build or not (old: this->IMG) | |
| 28 | + */ | |
| 29 | + private $imgBuilt; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * @var array Frames string sources (old: this->BUF) | |
| 33 | + */ | |
| 34 | + private $frameSources; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * @var integer Gif loop (old: this->LOP) | |
| 38 | + */ | |
| 39 | + private $loop; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * @var integer Gif dis (old: this->DIS) | |
| 43 | + */ | |
| 44 | + private $dis; | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * @var integer Gif color (old: this->COL) | |
| 48 | + */ | |
| 49 | + private $colour; | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * @var array (old: this->ERR) | |
| 53 | + */ | |
| 54 | + private $errors; | |
| 55 | + | |
| 56 | + // Methods | |
| 57 | + // =================================================================================== | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Constructor | |
| 61 | + */ | |
| 62 | + public function __construct() | |
| 63 | + { | |
| 64 | + $this->reset(); | |
| 65 | + | |
| 66 | + // Static data | |
| 67 | + $this->version = 'GifCreator: Under development'; | |
| 68 | + $this->errors = array( | |
| 69 | + 'ERR00' => 'Does not supported function for only one image.', | |
| 70 | + 'ERR01' => 'Source is not a GIF image.', | |
| 71 | + 'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.', | |
| 72 | + 'ERR03' => 'Does not make animation from animated GIF source.', | |
| 73 | + ); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Create the GIF string (old: GIFEncoder) | |
| 78 | + * | |
| 79 | + * @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs | |
| 80 | + * @param array $durations An array containing the duration of each frame | |
| 81 | + * @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop) | |
| 82 | + * | |
| 83 | + * @return string The GIF string source | |
| 84 | + */ | |
| 85 | + public function create($frames = array(), $durations = array(), $loop = 0) | |
| 86 | + { | |
| 87 | + if (!is_array($frames) && !is_array($GIF_tim)) { | |
| 88 | + | |
| 89 | + throw new \Exception($this->version.': '.$this->errors['ERR00']); | |
| 90 | + } | |
| 91 | + | |
| 92 | + $this->loop = ($loop > -1) ? $loop : 0; | |
| 93 | + $this->dis = 2; | |
| 94 | + | |
| 95 | + for ($i = 0; $i < count($frames); $i++) { | |
| 96 | + | |
| 97 | + if (is_resource($frames[$i])) { // Resource var | |
| 98 | + | |
| 99 | + $resourceImg = $frames[$i]; | |
| 100 | + | |
| 101 | + ob_start(); | |
| 102 | + imagegif($frames[$i]); | |
| 103 | + $this->frameSources[] = ob_get_contents(); | |
| 104 | + ob_end_clean(); | |
| 105 | + | |
| 106 | + } elseif (is_string($frames[$i])) { // File path or URL or Binary source code | |
| 107 | + | |
| 108 | + if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path | |
| 109 | + | |
| 110 | + $frames[$i] = file_get_contents($frames[$i]); | |
| 111 | + } | |
| 112 | + | |
| 113 | + $resourceImg = imagecreatefromstring($frames[$i]); | |
| 114 | + | |
| 115 | + ob_start(); | |
| 116 | + imagegif($resourceImg); | |
| 117 | + $this->frameSources[] = ob_get_contents(); | |
| 118 | + ob_end_clean(); | |
| 119 | + | |
| 120 | + } else { // Fail | |
| 121 | + | |
| 122 | + throw new \Exception($this->version.': '.$this->errors['ERR02'].' ('.$mode.')'); | |
| 123 | + } | |
| 124 | + | |
| 125 | + if ($i == 0) { | |
| 126 | + | |
| 127 | + $colour = imagecolortransparent($resourceImg); | |
| 128 | + } | |
| 129 | + | |
| 130 | + if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr($this->frameSources[$i], 0, 6) != 'GIF89a') { | |
| 131 | + | |
| 132 | + throw new \Exception($this->version.': '.$i.' '.$this->errors['ERR01']); | |
| 133 | + } | |
| 134 | + | |
| 135 | + for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))), $k = TRUE; $k; $j++) { | |
| 136 | + | |
| 137 | + switch ($this->frameSources[$i] { $j }) { | |
| 138 | + | |
| 139 | + case '!': | |
| 140 | + | |
| 141 | + if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') { | |
| 142 | + | |
| 143 | + throw new \Exception($this->version.': '.$this->errors['ERR03'].' ('.($i + 1).' source).'); | |
| 144 | + } | |
| 145 | + | |
| 146 | + break; | |
| 147 | + | |
| 148 | + case ';': | |
| 149 | + | |
| 150 | + $k = false; | |
| 151 | + break; | |
| 152 | + } | |
| 153 | + } | |
| 154 | + | |
| 155 | + unset($resourceImg); | |
| 156 | + } | |
| 157 | + | |
| 158 | + if (isset($colour)) { | |
| 159 | + | |
| 160 | + $this->colour = $colour; | |
| 161 | + | |
| 162 | + } else { | |
| 163 | + | |
| 164 | + $red = $green = $blue = 0; | |
| 165 | + $this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1; | |
| 166 | + } | |
| 167 | + | |
| 168 | + $this->gifAddHeader(); | |
| 169 | + | |
| 170 | + for ($i = 0; $i < count($this->frameSources); $i++) { | |
| 171 | + | |
| 172 | + $this->addGifFrames($i, $durations[$i]); | |
| 173 | + } | |
| 174 | + | |
| 175 | + $this->gifAddFooter(); | |
| 176 | + | |
| 177 | + return $this->gif; | |
| 178 | + } | |
| 179 | + | |
| 180 | + // Internals | |
| 181 | + // =================================================================================== | |
| 182 | + | |
| 183 | + /** | |
| 184 | + * Add the header gif string in its source (old: GIFAddHeader) | |
| 185 | + */ | |
| 186 | + public function gifAddHeader() | |
| 187 | + { | |
| 188 | + $cmap = 0; | |
| 189 | + | |
| 190 | + if (ord($this->frameSources[0] { 10 }) & 0x80) { | |
| 191 | + | |
| 192 | + $cmap = 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07)); | |
| 193 | + | |
| 194 | + $this->gif .= substr($this->frameSources[0], 6, 7); | |
| 195 | + $this->gif .= substr($this->frameSources[0], 13, $cmap); | |
| 196 | + $this->gif .= "!\377\13NETSCAPE2.0\3\1".$this->encodeAsciiToChar($this->loop)."\0"; | |
| 197 | + } | |
| 198 | + } | |
| 199 | + | |
| 200 | + /** | |
| 201 | + * Add the frame sources to the GIF string (old: GIFAddFrames) | |
| 202 | + * | |
| 203 | + * @param integer $i | |
| 204 | + * @param integer $d | |
| 205 | + */ | |
| 206 | + public function addGifFrames($i, $d) | |
| 207 | + { | |
| 208 | + $Locals_str = 13 + 3 * (2 << (ord($this->frameSources[ $i ] { 10 }) & 0x07)); | |
| 209 | + | |
| 210 | + $Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1; | |
| 211 | + $Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end); | |
| 212 | + | |
| 213 | + $Global_len = 2 << (ord($this->frameSources[0 ] { 10 }) & 0x07); | |
| 214 | + $Locals_len = 2 << (ord($this->frameSources[$i] { 10 }) & 0x07); | |
| 215 | + | |
| 216 | + $Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07))); | |
| 217 | + $Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))); | |
| 218 | + | |
| 219 | + $Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 0).chr(($d >> 0 ) & 0xFF).chr(($d >> 8) & 0xFF)."\x0\x0"; | |
| 220 | + | |
| 221 | + if ($this->colour > -1 && ord($this->frameSources[$i] { 10 }) & 0x80) { | |
| 222 | + | |
| 223 | + for ($j = 0; $j < (2 << (ord($this->frameSources[$i] { 10 } ) & 0x07)); $j++) { | |
| 224 | + | |
| 225 | + if (ord($Locals_rgb { 3 * $j + 0 }) == (($this->colour >> 16) & 0xFF) && | |
| 226 | + ord($Locals_rgb { 3 * $j + 1 }) == (($this->colour >> 8) & 0xFF) && | |
| 227 | + ord($Locals_rgb { 3 * $j + 2 }) == (($this->colour >> 0) & 0xFF) | |
| 228 | + ) { | |
| 229 | + $Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 1).chr(($d >> 0) & 0xFF).chr(($d >> 8) & 0xFF).chr($j)."\x0"; | |
| 230 | + break; | |
| 231 | + } | |
| 232 | + } | |
| 233 | + } | |
| 234 | + | |
| 235 | + switch ($Locals_tmp { 0 }) { | |
| 236 | + | |
| 237 | + case '!': | |
| 238 | + | |
| 239 | + $Locals_img = substr($Locals_tmp, 8, 10); | |
| 240 | + $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18); | |
| 241 | + | |
| 242 | + break; | |
| 243 | + | |
| 244 | + case ',': | |
| 245 | + | |
| 246 | + $Locals_img = substr($Locals_tmp, 0, 10); | |
| 247 | + $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10); | |
| 248 | + | |
| 249 | + break; | |
| 250 | + } | |
| 251 | + | |
| 252 | + if (ord($this->frameSources[$i] { 10 }) & 0x80 && $this->imgBuilt) { | |
| 253 | + | |
| 254 | + if ($Global_len == $Locals_len) { | |
| 255 | + | |
| 256 | + if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) { | |
| 257 | + | |
| 258 | + $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp; | |
| 259 | + | |
| 260 | + } else { | |
| 261 | + | |
| 262 | + $byte = ord($Locals_img { 9 }); | |
| 263 | + $byte |= 0x80; | |
| 264 | + $byte &= 0xF8; | |
| 265 | + $byte |= (ord($this->frameSources[0] { 10 }) & 0x07); | |
| 266 | + $Locals_img { 9 } = chr($byte); | |
| 267 | + $this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp; | |
| 268 | + } | |
| 269 | + | |
| 270 | + } else { | |
| 271 | + | |
| 272 | + $byte = ord($Locals_img { 9 }); | |
| 273 | + $byte |= 0x80; | |
| 274 | + $byte &= 0xF8; | |
| 275 | + $byte |= (ord($this->frameSources[$i] { 10 }) & 0x07); | |
| 276 | + $Locals_img { 9 } = chr($byte); | |
| 277 | + $this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp; | |
| 278 | + } | |
| 279 | + | |
| 280 | + } else { | |
| 281 | + | |
| 282 | + $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp; | |
| 283 | + } | |
| 284 | + | |
| 285 | + $this->imgBuilt = true; | |
| 286 | + } | |
| 287 | + | |
| 288 | + /** | |
| 289 | + * Add the gif string footer char (old: GIFAddFooter) | |
| 290 | + */ | |
| 291 | + public function gifAddFooter() | |
| 292 | + { | |
| 293 | + $this->gif .= ';'; | |
| 294 | + } | |
| 295 | + | |
| 296 | + /** | |
| 297 | + * Compare two block and return the version (old: GIFBlockCompare) | |
| 298 | + * | |
| 299 | + * @param string $globalBlock | |
| 300 | + * @param string $localBlock | |
| 301 | + * @param integer $length | |
| 302 | + * | |
| 303 | + * @return integer | |
| 304 | + */ | |
| 305 | + public function gifBlockCompare($globalBlock, $localBlock, $length) | |
| 306 | + { | |
| 307 | + for ($i = 0; $i < $length; $i++) { | |
| 308 | + | |
| 309 | + if ($globalBlock { 3 * $i + 0 } != $localBlock { 3 * $i + 0 } || | |
| 310 | + $globalBlock { 3 * $i + 1 } != $localBlock { 3 * $i + 1 } || | |
| 311 | + $globalBlock { 3 * $i + 2 } != $localBlock { 3 * $i + 2 }) { | |
| 312 | + | |
| 313 | + return 0; | |
| 314 | + } | |
| 315 | + } | |
| 316 | + | |
| 317 | + return 1; | |
| 318 | + } | |
| 319 | + | |
| 320 | + /** | |
| 321 | + * Encode an ASCII char into a string char (old: GIFWord) | |
| 322 | + * | |
| 323 | + * $param integer $char ASCII char | |
| 324 | + * | |
| 325 | + * @return string | |
| 326 | + */ | |
| 327 | + public function encodeAsciiToChar($char) | |
| 328 | + { | |
| 329 | + return (chr($char & 0xFF).chr(($char >> 8) & 0xFF)); | |
| 330 | + } | |
| 331 | + | |
| 332 | + /** | |
| 333 | + * Reset and clean the current object | |
| 334 | + */ | |
| 335 | + public function reset() | |
| 336 | + { | |
| 337 | + $this->frameSources; | |
| 338 | + $this->gif = 'GIF89a'; // the GIF header | |
| 339 | + $this->imgBuilt = false; | |
| 340 | + $this->loop = 0; | |
| 341 | + $this->dis = 2; | |
| 342 | + $this->colour = -1; | |
| 343 | + } | |
| 344 | + | |
| 345 | + // Getter / Setter | |
| 346 | + // =================================================================================== | |
| 347 | + | |
| 348 | + /** | |
| 349 | + * Get the final GIF image string (old: GetAnimation) | |
| 350 | + * | |
| 351 | + * @return string | |
| 352 | + */ | |
| 353 | + public function getGif() | |
| 354 | + { | |
| 355 | + return $this->gif; | |
| 356 | + } | |
| 357 | +} | |
| 358 | +?> | ... | ... |
| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | +# ================================ | |
| 2 | +# GifCreator | |
| 3 | +# ================================ | |
| 4 | + | |
| 5 | +GifCreator is a PHP class to create animated GIF from multiple images | |
| 6 | + | |
| 7 | +### For what ? | |
| 8 | + | |
| 9 | +This class helps you to create an animated GIF image: give multiple images and their duration and that's it ! | |
| 10 | + | |
| 11 | +### Usage | |
| 12 | + | |
| 13 | +**1 - Creation:** | |
| 14 | + | |
| 15 | +```php | |
| 16 | +// Create an array containing file paths, resource var (initialized with imagecreatefromXXX), | |
| 17 | +// image URLs or even binary code from image files. | |
| 18 | +// All sorted in order to appear. | |
| 19 | +$frames = array( | |
| 20 | + imagecreatefrompng("/../images/pic1.png"), // Resource var | |
| 21 | + "/../images/pic2.png", // Image file path | |
| 22 | + file_get_contents("/../images/pic3.jpg"), // Binary source code | |
| 23 | + 'http://thisisafakedomain.com/images/pic4.jpg', // URL | |
| 24 | +); | |
| 25 | + | |
| 26 | +// Create an array containing the duration (in millisecond) of each frames (in order too) | |
| 27 | +$durations = array(40, 80, 40, 20); | |
| 28 | + | |
| 29 | +// Initialize and create the GIF ! | |
| 30 | +$gc = new GifCreator(); | |
| 31 | +$gc->create($frames, $durations, 5); | |
| 32 | +``` | |
| 33 | +The 3rd parameter of create() method allows you to choose the number of loop of your animated gif before it stops. | |
| 34 | +In the previous example, I chose 5 loops. Set 0 (zero) to get an infinite loop. | |
| 35 | + | |
| 36 | +**2 - Get the result:** | |
| 37 | + | |
| 38 | +You can now get the animated GIF binary: | |
| 39 | + | |
| 40 | +```php | |
| 41 | +$gifBinary = $gc->getGif(); | |
| 42 | +``` | |
| 43 | + | |
| 44 | +Then you can show it in the navigator: | |
| 45 | + | |
| 46 | +```php | |
| 47 | +header('Content-type: image/gif'); | |
| 48 | +header('Content-Disposition: filename="butterfly.gif"'); | |
| 49 | +echo $gifBinary; | |
| 50 | +exit; | |
| 51 | +``` | |
| 52 | + | |
| 53 | +Or save it in a folder as a GIF: | |
| 54 | + | |
| 55 | +```php | |
| 56 | +file_put_contents('/myfolder/animated_picture.gif', $gifBinary); | |
| 57 | +``` | |
| 58 | + | |
| 59 | +### Behavior | |
| 60 | + | |
| 61 | +- The transparency is based on the first given frame. It will be saved only if you give multiple frames with same transparent background. | |
| 62 | +- The dimensions of the generated GIF are based on the first frame. If you need to resize your frames to get the same dimension, you can use | |
| 63 | +this class: https://github.com/Sybio/ImageWorkshop | |
| 64 | + | |
| 65 | +### About | |
| 66 | + | |
| 67 | +The class reuses some part of code of "GIFEncoder.class.php" by László Zsidi (thanks to him). | |
| 0 | 68 | \ No newline at end of file | ... | ... |