可以调整gif动画图片尺寸的很实用的php类

类的使用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 ?>

 

你可能感兴趣的:(PHP)