大家好,又见面了,我是全栈君
类的使用demo:
<?php
//http://www.cnblogs.com/roucheng/
require_once "roucheng.php";
$gr = new gifresizer;
$gr->temp_dir = "keleyi";
$gr->resize("keleyi.gif","keleyi_resized.gif",500,500);
?>
类的源代码,保存为roucheng.php文件:
1 <?
2 /**
3 *
4 * Resizes Animated GIF Files
5 *
6 * ///IMPORTANT NOTE: The script needs a temporary directory where all the frames should be extracted.
7 * Create a directory with a 777 permission level and write the path into $temp_dir variable below.
8 *
9 * Default directory is "frames".
10 */
11
12 class gifresizer {
13
14 public $temp_dir = "frames";
15 private $pointer = 0;
16 private $index = 0;
17 private $globaldata = array();
18 private $imagedata = array();
19 private $imageinfo = array();
20 private $handle = 0;
21 private $orgvars = array();
22 private $encdata = array();
23 private $parsedfiles = array();
24 private $originalwidth = 0;
25 private $originalheight = 0;
26 private $wr,$hr;
27 private $props = array();
28 private $decoding = false;
29
30 /**
31 * Public part of the class
32 *
33 * @orgfile - Original file path
34 * @newfile - New filename with path
35 * @width - Desired image width
36 * @height - Desired image height
37 */
38 function resize($orgfile,$newfile,$width,$height){
39 $this->decode($orgfile);
40 $this->wr=$width/$this->originalwidth;
41 $this->hr=$height/$this->originalheight;
42 $this->resizeframes();
43 $this->encode($newfile,$width,$height);
44 $this->clearframes();
45 }
46
47 /**
48 * GIF Decoder function.
49 * Parses the GIF animation into single frames.
50 */
51 private function decode($filename){
52 $this->decoding = true;
53 $this->clearvariables();
54 $this->loadfile($filename);
55 $this->get_gif_header();
56 $this->get_graphics_extension(0);
57 $this->get_application_data();
58 $this->get_application_data();
59 $this->get_image_block(0);
60 $this->get_graphics_extension(1);
61 $this->get_comment_data();
62 $this->get_application_data();
63 $this->get_image_block(1);
64 while(!$this->checkbyte(0x3b) && !$this->checkEOF()){
65 $this->get_comment_data(1);
66 $this->get_graphics_extension(2);
67 $this->get_image_block(2);
68 }
69 $this->writeframes(time());
70 $this->closefile();
71 $this->decoding = false;
72 }
73
74 /**
75 * GIF Encoder function.
76 * Combines the parsed GIF frames into one single animation.
77 */
78 private function encode($new_filename,$newwidth,$newheight){
79 $mystring = "";
80 $this->pointer = 0;
81 $this->imagedata = array();
82 $this->imageinfo = array();
83 $this->handle = 0;
84 $this->index=0;
85
86 $k=0;
87 foreach($this->parsedfiles as $imagepart){
88 $this->loadfile($imagepart);
89 $this->get_gif_header();
90 $this->get_application_data();
91 $this->get_comment_data();
92 $this->get_graphics_extension(0);
93 $this->get_image_block(0);
94
95 //get transparent color index and color
96 if(isset($this->encdata[$this->index-1]))
97 $gxdata = $this->encdata[$this->index-1]["graphicsextension"];
98 else
99 $gxdata = null;
100 $ghdata = $this->imageinfo["gifheader"];
101 $trcolor = "";
102 $hastransparency=($gxdata[3]&&1==1);
103
104 if($hastransparency){
105 $trcx = ord($gxdata[6]);
106 $trcolor = substr($ghdata,13+$trcx*3,3);
107 }
108
109 //global color table to image data;
110 $this->transfercolortable($this->imageinfo["gifheader"],$this->imagedata[$this->index-1]["imagedata"]);
111
112 $imageblock = &$this->imagedata[$this->index-1]["imagedata"];
113
114 //if transparency exists transfer transparency index
115 if($hastransparency){
116 $haslocalcolortable = ((ord($imageblock[9])&128)==128);
117 if($haslocalcolortable){
118 //local table exists. determine boundaries and look for it.
119 $tablesize=(pow(2,(ord($imageblock[9])&7)+1)*3)+10;
120 $this->orgvars[$this->index-1]["transparent_color_index"] =
121 ((strrpos(substr($this->imagedata[$this->index-1]["imagedata"],0,$tablesize),$trcolor)-10)/3);
122 }else{
123 //local table doesnt exist, look at the global one.
124 $tablesize=(pow(2,(ord($gxdata[10])&7)+1)*3)+10;
125 $this->orgvars[$this->index-1]["transparent_color_index"] =
126 ((strrpos(substr($ghdata,0,$tablesize),$trcolor)-10)/3);
127 }
128 }
129
130 //apply original delay time,transparent index and disposal values to graphics extension
131
132 if(!$this->imagedata[$this->index-1]["graphicsextension"]) $this->imagedata[$this->index-1]["graphicsextension"] = chr(0x21).chr(0xf9).chr(0x04).chr(0x00).chr(0x00).chr(0x00).chr(0x00).chr(0x00);
133
134 $imagedata = &$this->imagedata[$this->index-1]["graphicsextension"];
135
136 $imagedata[3] = chr((ord($imagedata[3]) & 0xE3) | ($this->orgvars[$this->index-1]["disposal_method"] << 2));
137 $imagedata[4] = chr(($this->orgvars[$this->index-1]["delay_time"] % 256));
138 $imagedata[5] = chr(floor($this->orgvars[$this->index-1]["delay_time"] / 256));
139 if($hastransparency){
140 $imagedata[6] = chr($this->orgvars[$this->index-1]["transparent_color_index"]);
141 }
142 $imagedata[3] = chr(ord($imagedata[3])|$hastransparency);
143
144 //apply calculated left and top offset
145 $imageblock[1] = chr(round(($this->orgvars[$this->index-1]["offset_left"]*$this->wr) % 256));
146 $imageblock[2] = chr(floor(($this->orgvars[$this->index-1]["offset_left"]*$this->wr) / 256));
147 $imageblock[3] = chr(round(($this->orgvars[$this->index-1]["offset_top"]*$this->hr) % 256));
148 $imageblock[4] = chr(floor(($this->orgvars[$this->index-1]["offset_top"]*$this->hr) / 256));
149
150 if($this->index==1){
151 if(!isset($this->imageinfo["applicationdata"]) || !$this->imageinfo["applicationdata"])
152 $this->imageinfo["applicationdata"]=chr(0x21).chr(0xff).chr(0x0b)."NETSCAPE2.0".chr(0x03).chr(0x01).chr(0x00).chr(0x00).chr(0x00);
153 if(!isset($this->imageinfo["commentdata"]) || !$this->imageinfo["commentdata"])
154 $this->imageinfo["commentdata"] = chr(0x21).chr(0xfe).chr(0x10)."PHPGIFRESIZER1.0".chr(0);
155 $mystring .= $this->orgvars["gifheader"]. $this->imageinfo["applicationdata"].$this->imageinfo["commentdata"];
156 if(isset($this->orgvars["hasgx_type_0"]) && $this->orgvars["hasgx_type_0"]) $mystring .= $this->globaldata["graphicsextension_0"];
157 if(isset($this->orgvars["hasgx_type_1"]) && $this->orgvars["hasgx_type_1"]) $mystring .= $this->globaldata["graphicsextension"];
158 }
159
160 $mystring .= $imagedata . $imageblock;
161 $k++;
162 $this->closefile();
163 }
164
165 $mystring .= chr(0x3b);
166
167 //applying new width & height to gif header
168 $mystring[6] = chr($newwidth % 256);
169 $mystring[7] = chr(floor($newwidth / 256));
170 $mystring[8] = chr($newheight % 256);
171 $mystring[9] = chr(floor($newheight / 256));
172 $mystring[11]= $this->orgvars["background_color"];
173 //if(file_exists($new_filename)){unlink($new_filename);}
174 file_put_contents($new_filename,$mystring);
175 }
176
177 /**
178 * Variable Reset function
179 * If a instance is used multiple times, it's needed. Trust me.
180 */
181 private function clearvariables(){
182 $this->pointer = 0;
183 $this->index = 0;
184 $this->imagedata = array();
185 $this->imageinfo = array();
186 $this->handle = 0;
187 $this->parsedfiles = array();
188 }
189
190 /**
191 * Clear Frames function
192 * For deleting the frames after encoding.
193 */
194 private function clearframes(){
195 foreach($this->parsedfiles as $temp_frame){
196 unlink($temp_frame);
197 }
198 }
199
200 /**
201 * Frame Writer
202 * Writes the GIF frames into files.
203 */
204 private function writeframes($prepend){
205 for($i=0;$i<sizeof($this->imagedata);$i++){
206 file_put_contents($this->temp_dir."/frame_".$prepend."_".str_pad($i,2,"0",STR_PAD_LEFT).".gif",$this->imageinfo["gifheader"].$this->imagedata[$i]["graphicsextension"].$this->imagedata[$i]["imagedata"].chr(0x3b));
207 $this->parsedfiles[]=$this->temp_dir."/frame_".$prepend."_".str_pad($i,2,"0",STR_PAD_LEFT).".gif";
208 }
209 }
210
211 /**
212 * Color Palette Transfer Device
213 * Transferring Global Color Table (GCT) from frames into Local Color Tables in animation.
214 */
215 private function transfercolortable($src,&$dst){
216 //src is gif header,dst is image data block
217 //if global color table exists,transfer it
218 if((ord($src[10])&128)==128){
219 //Gif Header Global Color Table Length
220 $ghctl = pow(2,$this->readbits(ord($src[10]),5,3)+1)*3;
221 //cut global color table from gif header
222 $ghgct = substr($src,13,$ghctl);
223 //check image block color table length
224 if((ord($dst[9])&128)==128){
225 //Image data contains color table. skip.
226 }else{
227 //Image data needs a color table.
228 //get last color table length so we can truncate the dummy color table
229 $idctl = pow(2,$this->readbits(ord($dst[9]),5,3)+1)*3;
230 //set color table flag and length
231 $dst[9] = chr(ord($dst[9]) | (0x80 | (log($ghctl/3,2)-1)));
232 //inject color table
233 $dst = substr($dst,0,10).$ghgct.substr($dst,-1*strlen($dst)+10);
234 }
235 }else{
236 //global color table doesn't exist. skip.
237 }
238 }
239
240 /**
241 * GIF Parser Functions.
242 * Below functions are the main structure parser components.
243 */
244 private function get_gif_header(){
245 $this->p_forward(10);
246 if($this->readbits(($mybyte=$this->readbyte_int()),0,1)==1){
247 $this->p_forward(2);
248 $this->p_forward(pow(2,$this->readbits($mybyte,5,3)+1)*3);
249 }else{
250 $this->p_forward(2);
251 }
252
253 $this->imageinfo["gifheader"]=$this->datapart(0,$this->pointer);
254 if($this->decoding){
255 $this->orgvars["gifheader"]=$this->imageinfo["gifheader"];
256 $this->originalwidth = ord($this->orgvars["gifheader"][7])*256+ord($this->orgvars["gifheader"][6]);
257 $this->originalheight = ord($this->orgvars["gifheader"][9])*256+ord($this->orgvars["gifheader"][8]);
258 $this->orgvars["background_color"]=$this->orgvars["gifheader"][11];
259 }
260
261 }
262 //-------------------------------------------------------
263 private function get_application_data(){
264 $startdata = $this->readbyte(2);
265 if($startdata==chr(0x21).chr(0xff)){
266 $start = $this->pointer - 2;
267 $this->p_forward($this->readbyte_int());
268 $this->read_data_stream($this->readbyte_int());
269 $this->imageinfo["applicationdata"] = $this->datapart($start,$this->pointer-$start);
270 }else{
271 $this->p_rewind(2);
272 }
273 }
274 //-------------------------------------------------------
275 private function get_comment_data(){
276 $startdata = $this->readbyte(2);
277 if($startdata==chr(0x21).chr(0xfe)){
278 $start = $this->pointer - 2;
279 $this->read_data_stream($this->readbyte_int());
280 $this->imageinfo["commentdata"] = $this->datapart($start,$this->pointer-$start);
281 }else{
282 $this->p_rewind(2);
283 }
284 }
285 //-------------------------------------------------------
286 private function get_graphics_extension($type){
287 $startdata = $this->readbyte(2);
288 if($startdata==chr(0x21).chr(0xf9)){
289 $start = $this->pointer - 2;
290 $this->p_forward($this->readbyte_int());
291 $this->p_forward(1);
292 if($type==2){
293 $this->imagedata[$this->index]["graphicsextension"] = $this->datapart($start,$this->pointer-$start);
294 }else if($type==1){
295 $this->orgvars["hasgx_type_1"] = 1;
296 $this->globaldata["graphicsextension"] = $this->datapart($start,$this->pointer-$start);
297 }else if($type==0 && $this->decoding==false){
298 $this->encdata[$this->index]["graphicsextension"] = $this->datapart($start,$this->pointer-$start);
299 }else if($type==0 && $this->decoding==true){
300 $this->orgvars["hasgx_type_0"] = 1;
301 $this->globaldata["graphicsextension_0"] = $this->datapart($start,$this->pointer-$start);
302 }
303 }else{
304 $this->p_rewind(2);
305 }
306 }
307 //-------------------------------------------------------
308 private function get_image_block($type){
309 if($this->checkbyte(0x2c)){
310 $start = $this->pointer;
311 $this->p_forward(9);
312 if($this->readbits(($mybyte=$this->readbyte_int()),0,1)==1){
313 $this->p_forward(pow(2,$this->readbits($mybyte,5,3)+1)*3);
314 }
315 $this->p_forward(1);
316 $this->read_data_stream($this->readbyte_int());
317 $this->imagedata[$this->index]["imagedata"] = $this->datapart($start,$this->pointer-$start);
318
319 if($type==0){
320 $this->orgvars["hasgx_type_0"] = 0;
321 if(isset($this->globaldata["graphicsextension_0"]))
322 $this->imagedata[$this->index]["graphicsextension"]=$this->globaldata["graphicsextension_0"];
323 else
324 $this->imagedata[$this->index]["graphicsextension"]=null;
325 unset($this->globaldata["graphicsextension_0"]);
326 }elseif($type==1){
327 if(isset($this->orgvars["hasgx_type_1"]) && $this->orgvars["hasgx_type_1"]==1){
328 $this->orgvars["hasgx_type_1"] = 0;
329 $this->imagedata[$this->index]["graphicsextension"]=$this->globaldata["graphicsextension"];
330 unset($this->globaldata["graphicsextension"]);
331 }else{
332 $this->orgvars["hasgx_type_0"] = 0;
333 $this->imagedata[$this->index]["graphicsextension"]=$this->globaldata["graphicsextension_0"];
334 unset($this->globaldata["graphicsextension_0"]);
335 }
336 }
337
338 $this->parse_image_data();
339 $this->index++;
340
341 }
342 }
343 //-------------------------------------------------------
344 private function parse_image_data(){
345 $this->imagedata[$this->index]["disposal_method"] = $this->get_imagedata_bit("ext",3,3,3);
346 $this->imagedata[$this->index]["user_input_flag"] = $this->get_imagedata_bit("ext",3,6,1);
347 $this->imagedata[$this->index]["transparent_color_flag"] = $this->get_imagedata_bit("ext",3,7,1);
348 $this->imagedata[$this->index]["delay_time"] = $this->dualbyteval($this->get_imagedata_byte("ext",4,2));
349 $this->imagedata[$this->index]["transparent_color_index"] = ord($this->get_imagedata_byte("ext",6,1));
350 $this->imagedata[$this->index]["offset_left"] = $this->dualbyteval($this->get_imagedata_byte("dat",1,2));
351 $this->imagedata[$this->index]["offset_top"] = $this->dualbyteval($this->get_imagedata_byte("dat",3,2));
352 $this->imagedata[$this->index]["width"] = $this->dualbyteval($this->get_imagedata_byte("dat",5,2));
353 $this->imagedata[$this->index]["height"] = $this->dualbyteval($this->get_imagedata_byte("dat",7,2));
354 $this->imagedata[$this->index]["local_color_table_flag"] = $this->get_imagedata_bit("dat",9,0,1);
355 $this->imagedata[$this->index]["interlace_flag"] = $this->get_imagedata_bit("dat",9,1,1);
356 $this->imagedata[$this->index]["sort_flag"] = $this->get_imagedata_bit("dat",9,2,1);
357 $this->imagedata[$this->index]["color_table_size"] = pow(2,$this->get_imagedata_bit("dat",9,5,3)+1)*3;
358 $this->imagedata[$this->index]["color_table"] = substr($this->imagedata[$this->index]["imagedata"],10,$this->imagedata[$this->index]["color_table_size"]);
359 $this->imagedata[$this->index]["lzw_code_size"] = ord($this->get_imagedata_byte("dat",10,1));
360 if($this->decoding){
361 $this->orgvars[$this->index]["transparent_color_flag"] = $this->imagedata[$this->index]["transparent_color_flag"];
362 $this->orgvars[$this->index]["transparent_color_index"] = $this->imagedata[$this->index]["transparent_color_index"];
363 $this->orgvars[$this->index]["delay_time"] = $this->imagedata[$this->index]["delay_time"];
364 $this->orgvars[$this->index]["disposal_method"] = $this->imagedata[$this->index]["disposal_method"];
365 $this->orgvars[$this->index]["offset_left"] = $this->imagedata[$this->index]["offset_left"];
366 $this->orgvars[$this->index]["offset_top"] = $this->imagedata[$this->index]["offset_top"];
367 }
368 }
369 //-------------------------------------------------------
370 private function get_imagedata_byte($type,$start,$length){
371 if($type=="ext")
372 return substr($this->imagedata[$this->index]["graphicsextension"],$start,$length);
373 elseif($type=="dat")
374 return substr($this->imagedata[$this->index]["imagedata"],$start,$length);
375 }
376 //-------------------------------------------------------
377 private function get_imagedata_bit($type,$byteindex,$bitstart,$bitlength){
378 if($type=="ext")
379 return $this->readbits(ord(substr($this->imagedata[$this->index]["graphicsextension"],$byteindex,1)),$bitstart,$bitlength);
380 elseif($type=="dat")
381 return $this->readbits(ord(substr($this->imagedata[$this->index]["imagedata"],$byteindex,1)),$bitstart,$bitlength);
382 }
383 //-------------------------------------------------------
384 private function dualbyteval($s){
385 $i = ord($s[1])*256 + ord($s[0]);
386 return $i;
387 }
388 //------------ Helper Functions ---------------------
389 private function read_data_stream($first_length){
390 $this->p_forward($first_length);
391 $length=$this->readbyte_int();
392 if($length!=0) {
393 while($length!=0){
394 $this->p_forward($length);
395 $length=$this->readbyte_int();
396 }
397 }
398 return true;
399 }
400 //-------------------------------------------------------
401 private function loadfile($filename){
402 $this->handle = fopen($filename,"rb");
403 $this->pointer = 0;
404 }
405 //-------------------------------------------------------
406 private function closefile(){
407 fclose($this->handle);
408 $this->handle=0;
409 }
410 //-------------------------------------------------------
411 private function readbyte($byte_count){
412 $data = fread($this->handle,$byte_count);
413 $this->pointer += $byte_count;
414 return $data;
415 }
416 //-------------------------------------------------------
417 private function readbyte_int(){
418 $data = fread($this->handle,1);
419 $this->pointer++;
420 return ord($data);
421 }
422 //-------------------------------------------------------
423 private function readbits($byte,$start,$length){
424 $bin = str_pad(decbin($byte),8,"0",STR_PAD_LEFT);
425 $data = substr($bin,$start,$length);
426 return bindec($data);
427 }
428 //-------------------------------------------------------
429 private function p_rewind($length){
430 $this->pointer-=$length;
431 fseek($this->handle,$this->pointer);
432 }
433 //-------------------------------------------------------
434 private function p_forward($length){
435 $this->pointer+=$length;
436 fseek($this->handle,$this->pointer);
437 }
438 //-------------------------------------------------------
439 private function datapart($start,$length){
440 fseek($this->handle,$start);
441 $data = fread($this->handle,$length);
442 fseek($this->handle,$this->pointer);
443 return $data;
444 }
445 //-------------------------------------------------------
446 private function checkbyte($byte){
447 if(fgetc($this->handle)==chr($byte)){
448 fseek($this->handle,$this->pointer);
449 return true;
450 }else{
451 fseek($this->handle,$this->pointer);
452 return false;
453 }
454 }
455 //-------------------------------------------------------
456 private function checkEOF(){
457 if(fgetc($this->handle)===false){
458 return true;
459 }else{
460 fseek($this->handle,$this->pointer);
461 return false;
462 }
463 }
464 //-------------------------------------------------------
465 /**
466 * Debug Functions. keleyi.com
467 * Parses the GIF animation into single frames.
468 */
469 private function debug($string){
470 echo "<pre>";
471 for($i=0;$i<strlen($string);$i++){
472 echo str_pad(dechex(ord($string[$i])),2,"0",STR_PAD_LEFT). " ";
473 }
474 echo "</pre>";
475 }
476 //-------------------------------------------------------
477 private function debuglen($var,$len){
478 echo "<pre>";
479 for($i=0;$i<$len;$i++){
480 echo str_pad(dechex(ord($var[$i])),2,"0",STR_PAD_LEFT). " ";
481 }
482 echo "</pre>";
483 }
484 //-------------------------------------------------------
485 private function debugstream($length){
486 $this->debug($this->datapart($this->pointer,$length));
487 }
488 //-------------------------------------------------------
489 /**
490 * GD Resizer Device
491 * Resizes the animation frames
492 */
493 private function resizeframes(){
494 $k=0;
495 foreach($this->parsedfiles as $img){
496 $src = imagecreatefromgif($img);
497 $sw = $this->imagedata[$k]["width"];
498 $sh = $this->imagedata[$k]["height"];
499 $nw = round($sw * $this->wr);
500 $nh = round($sh * $this->hr);
501 $sprite = imagecreatetruecolor($nw,$nh);
502 $trans = imagecolortransparent($sprite);
503 imagealphablending($sprite, false);
504 imagesavealpha($sprite, true);
505 imagepalettecopy($sprite,$src);
506 imagefill($sprite,0,0,imagecolortransparent($src));
507 imagecolortransparent($sprite,imagecolortransparent($src));
508 imagecopyresized($sprite,$src,0,0,0,0,$nw,$nh,$sw,$sh);
509 imagegif($sprite,$img);
510 imagedestroy($sprite);
511 imagedestroy($src);
512 $k++;
513 }
514 }
515 }
516
517
518 ?>
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/120780.html原文链接:https://javaforall.cn
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有