当前位置:Gxlcms > PHP教程 > 一个很实用的类,php调整gif图片的尺寸!

一个很实用的类,php调整gif图片的尺寸!

时间:2021-07-01 10:21:17 帮助过:24人阅读

这个类可以对GIF格式的动态文件进行调整。提取动态图片帧文件到一个临时目录中。调整图像的大小并提取和重建成动画的GIF格式的新文件。

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

人气教程排行