PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/thumb/phpthumb.gif.php

https://bitbucket.org/webnroll/cosyx
PHP | 1173 lines | 846 code | 206 blank | 121 comment | 156 complexity | 56ac8112cee218df07ba7e9a0e7ac2f0 MD5 | raw file
  1. <?php
  2. ///////////////////////////////////////////////////////////////////////////////////////////////////
  3. // GIF Util - (C) 2003 Yamasoft (S/C)
  4. // http://www.yamasoft.com
  5. // All Rights Reserved
  6. // This file can be freely copied, distributed, modified, updated by anyone under the only
  7. // condition to leave the original address (Yamasoft, http://www.yamasoft.com) and this header.
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////
  9. // <gif> = gif_loadFile(filename, [index])
  10. // <bool> = gif_getSize(<gif> or filename, &width, &height)
  11. // <bool> = gif_outputAsPng(<gif>, filename, [bgColor])
  12. // <bool> = gif_outputAsBmp(<gif>, filename, [bgcolor])
  13. // <bool> = gif_outputAsJpeg(<gif>, filename, [bgcolor]) - use cjpeg if available otherwise uses GD
  14. ///////////////////////////////////////////////////////////////////////////////////////////////////
  15. // Original code by Fabien Ezber
  16. // Modified by James Heinrich <info@silisoftware.com> for use in phpThumb() - December 10, 2003
  17. // * Added function gif_loadFileToGDimageResource() - this returns a GD image resource
  18. // * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not
  19. // available, in which case it will attempt to output JPEG using GD functions
  20. // * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans)
  21. // otherwise warnings are generated if error_reporting == E_ALL
  22. ///////////////////////////////////////////////////////////////////////////////////////////////////
  23. function gif_loadFile($lpszFileName, $iIndex = 0)
  24. {
  25. $gif = new CGIF();
  26. if ($gif->loadFile($lpszFileName, $iIndex)) {
  27. return $gif;
  28. }
  29. return false;
  30. }
  31. ///////////////////////////////////////////////////////////////////////////////////////////////////
  32. // Added by James Heinrich <info@silisoftware.com> - December 10, 2003
  33. function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1)
  34. {
  35. if ($gif = gif_loadFile($gifFilename)) {
  36. if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
  37. // shouldn't take nearly this long
  38. set_time_limit(120);
  39. }
  40. // general strategy: convert raw data to PNG then convert PNG data to GD image resource
  41. $PNGdata = $gif->getPng($bgColor);
  42. if ($img = @ImageCreateFromString($PNGdata)) {
  43. // excellent - PNG image data successfully converted to GD image
  44. return $img;
  45. } elseif ($img = $gif->getGD_PixelPlotterVersion()) {
  46. // problem: ImageCreateFromString() didn't like the PNG image data.
  47. // This has been known to happen in PHP v4.0.6
  48. // solution: take the raw image data and create a new GD image and plot
  49. // pixel-by-pixel on the GD image. This is extremely slow, but it does
  50. // work and a slow solution is better than no solution, right? :)
  51. return $img;
  52. }
  53. }
  54. return false;
  55. }
  56. ///////////////////////////////////////////////////////////////////////////////////////////////////
  57. function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1)
  58. {
  59. if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
  60. return false;
  61. }
  62. $fd = $gif->getBmp($bgColor);
  63. if (strlen($fd) <= 0) {
  64. return false;
  65. }
  66. if (!($fh = @fopen($lpszFileName, 'wb'))) {
  67. return false;
  68. }
  69. @fwrite($fh, $fd, strlen($fd));
  70. @fflush($fh);
  71. @fclose($fh);
  72. return true;
  73. }
  74. ///////////////////////////////////////////////////////////////////////////////////////////////////
  75. function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1)
  76. {
  77. if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
  78. return false;
  79. }
  80. $fd = $gif->getPng($bgColor);
  81. if (strlen($fd) <= 0) {
  82. return false;
  83. }
  84. if (!($fh = @fopen($lpszFileName, 'wb'))) {
  85. return false;
  86. }
  87. @fwrite($fh, $fd, strlen($fd));
  88. @fflush($fh);
  89. @fclose($fh);
  90. return true;
  91. }
  92. ///////////////////////////////////////////////////////////////////////////////////////////////////
  93. function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1)
  94. {
  95. // JPEG output that does not require cjpeg added by James Heinrich <info@silisoftware.com> - December 10, 2003
  96. if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) {
  97. if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) {
  98. exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null');
  99. @unLink($lpszFileName.'.bmp');
  100. if (@file_exists($lpszFileName)) {
  101. if (@fileSize($lpszFileName) > 0) {
  102. return true;
  103. }
  104. @unLink($lpszFileName);
  105. }
  106. }
  107. } else {
  108. // either Windows, or cjpeg not found in path
  109. if ($img = @ImageCreateFromString($gif->getPng($bgColor))) {
  110. if (@ImageJPEG($img, $lpszFileName)) {
  111. return true;
  112. }
  113. }
  114. }
  115. return false;
  116. }
  117. ///////////////////////////////////////////////////////////////////////////////////////////////////
  118. function gif_getSize($gif, &$width, &$height)
  119. {
  120. if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) {
  121. $width = $gif->width();
  122. $height = $gif->height();
  123. } elseif (@file_exists($gif)) {
  124. $myGIF = new CGIF();
  125. if (!$myGIF->getSize($gif, $width, $height)) {
  126. return false;
  127. }
  128. } else {
  129. return false;
  130. }
  131. return true;
  132. }
  133. ///////////////////////////////////////////////////////////////////////////////////////////////////
  134. class CGIFLZW
  135. {
  136. var $MAX_LZW_BITS;
  137. var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
  138. var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
  139. ///////////////////////////////////////////////////////////////////////////
  140. // CONSTRUCTOR
  141. function CGIFLZW()
  142. {
  143. $this->MAX_LZW_BITS = 12;
  144. unSet($this->Next);
  145. unSet($this->Vals);
  146. unSet($this->Stack);
  147. unSet($this->Buf);
  148. $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1);
  149. $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1);
  150. $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
  151. $this->Buf = range(0, 279);
  152. }
  153. ///////////////////////////////////////////////////////////////////////////
  154. function deCompress($data, &$datLen)
  155. {
  156. $stLen = strlen($data);
  157. $datLen = 0;
  158. $ret = '';
  159. // INITIALIZATION
  160. $this->LZWCommand($data, true);
  161. while (($iIndex = $this->LZWCommand($data, false)) >= 0) {
  162. $ret .= chr($iIndex);
  163. }
  164. $datLen = $stLen - strlen($data);
  165. if ($iIndex != -2) {
  166. return false;
  167. }
  168. return $ret;
  169. }
  170. ///////////////////////////////////////////////////////////////////////////
  171. function LZWCommand(&$data, $bInit)
  172. {
  173. if ($bInit) {
  174. $this->SetCodeSize = ord($data{0});
  175. $data = substr($data, 1);
  176. $this->CodeSize = $this->SetCodeSize + 1;
  177. $this->ClearCode = 1 << $this->SetCodeSize;
  178. $this->EndCode = $this->ClearCode + 1;
  179. $this->MaxCode = $this->ClearCode + 2;
  180. $this->MaxCodeSize = $this->ClearCode << 1;
  181. $this->GetCode($data, $bInit);
  182. $this->Fresh = 1;
  183. for ($i = 0; $i < $this->ClearCode; $i++) {
  184. $this->Next[$i] = 0;
  185. $this->Vals[$i] = $i;
  186. }
  187. for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
  188. $this->Next[$i] = 0;
  189. $this->Vals[$i] = 0;
  190. }
  191. $this->sp = 0;
  192. return 1;
  193. }
  194. if ($this->Fresh) {
  195. $this->Fresh = 0;
  196. do {
  197. $this->FirstCode = $this->GetCode($data, $bInit);
  198. $this->OldCode = $this->FirstCode;
  199. }
  200. while ($this->FirstCode == $this->ClearCode);
  201. return $this->FirstCode;
  202. }
  203. if ($this->sp > 0) {
  204. $this->sp--;
  205. return $this->Stack[$this->sp];
  206. }
  207. while (($Code = $this->GetCode($data, $bInit)) >= 0) {
  208. if ($Code == $this->ClearCode) {
  209. for ($i = 0; $i < $this->ClearCode; $i++) {
  210. $this->Next[$i] = 0;
  211. $this->Vals[$i] = $i;
  212. }
  213. for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
  214. $this->Next[$i] = 0;
  215. $this->Vals[$i] = 0;
  216. }
  217. $this->CodeSize = $this->SetCodeSize + 1;
  218. $this->MaxCodeSize = $this->ClearCode << 1;
  219. $this->MaxCode = $this->ClearCode + 2;
  220. $this->sp = 0;
  221. $this->FirstCode = $this->GetCode($data, $bInit);
  222. $this->OldCode = $this->FirstCode;
  223. return $this->FirstCode;
  224. }
  225. if ($Code == $this->EndCode) {
  226. return -2;
  227. }
  228. $InCode = $Code;
  229. if ($Code >= $this->MaxCode) {
  230. $this->Stack[$this->sp] = $this->FirstCode;
  231. $this->sp++;
  232. $Code = $this->OldCode;
  233. }
  234. while ($Code >= $this->ClearCode) {
  235. $this->Stack[$this->sp] = $this->Vals[$Code];
  236. $this->sp++;
  237. if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
  238. return -1;
  239. $Code = $this->Next[$Code];
  240. }
  241. $this->FirstCode = $this->Vals[$Code];
  242. $this->Stack[$this->sp] = $this->FirstCode;
  243. $this->sp++;
  244. if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) {
  245. $this->Next[$Code] = $this->OldCode;
  246. $this->Vals[$Code] = $this->FirstCode;
  247. $this->MaxCode++;
  248. if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) {
  249. $this->MaxCodeSize *= 2;
  250. $this->CodeSize++;
  251. }
  252. }
  253. $this->OldCode = $InCode;
  254. if ($this->sp > 0) {
  255. $this->sp--;
  256. return $this->Stack[$this->sp];
  257. }
  258. }
  259. return $Code;
  260. }
  261. ///////////////////////////////////////////////////////////////////////////
  262. function GetCode(&$data, $bInit)
  263. {
  264. if ($bInit) {
  265. $this->CurBit = 0;
  266. $this->LastBit = 0;
  267. $this->Done = 0;
  268. $this->LastByte = 2;
  269. return 1;
  270. }
  271. if (($this->CurBit + $this->CodeSize) >= $this->LastBit) {
  272. if ($this->Done) {
  273. if ($this->CurBit >= $this->LastBit) {
  274. // Ran off the end of my bits
  275. return 0;
  276. }
  277. return -1;
  278. }
  279. $this->Buf[0] = $this->Buf[$this->LastByte - 2];
  280. $this->Buf[1] = $this->Buf[$this->LastByte - 1];
  281. $Count = ord($data{0});
  282. $data = substr($data, 1);
  283. if ($Count) {
  284. for ($i = 0; $i < $Count; $i++) {
  285. $this->Buf[2 + $i] = ord($data{$i});
  286. }
  287. $data = substr($data, $Count);
  288. } else {
  289. $this->Done = 1;
  290. }
  291. $this->LastByte = 2 + $Count;
  292. $this->CurBit = ($this->CurBit - $this->LastBit) + 16;
  293. $this->LastBit = (2 + $Count) << 3;
  294. }
  295. $iRet = 0;
  296. for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) {
  297. $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
  298. }
  299. $this->CurBit += $this->CodeSize;
  300. return $iRet;
  301. }
  302. }
  303. ///////////////////////////////////////////////////////////////////////////////////////////////////
  304. class CGIFCOLORTABLE
  305. {
  306. var $m_nColors;
  307. var $m_arColors;
  308. ///////////////////////////////////////////////////////////////////////////
  309. // CONSTRUCTOR
  310. function CGIFCOLORTABLE()
  311. {
  312. unSet($this->m_nColors);
  313. unSet($this->m_arColors);
  314. }
  315. ///////////////////////////////////////////////////////////////////////////
  316. function load($lpData, $num)
  317. {
  318. $this->m_nColors = 0;
  319. $this->m_arColors = array();
  320. for ($i = 0; $i < $num; $i++) {
  321. $rgb = substr($lpData, $i * 3, 3);
  322. if (strlen($rgb) < 3) {
  323. return false;
  324. }
  325. $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0});
  326. $this->m_nColors++;
  327. }
  328. return true;
  329. }
  330. ///////////////////////////////////////////////////////////////////////////
  331. function toString()
  332. {
  333. $ret = '';
  334. for ($i = 0; $i < $this->m_nColors; $i++) {
  335. $ret .=
  336. chr(($this->m_arColors[$i] & 0x000000FF)) . // R
  337. chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G
  338. chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B
  339. }
  340. return $ret;
  341. }
  342. ///////////////////////////////////////////////////////////////////////////
  343. function toRGBQuad()
  344. {
  345. $ret = '';
  346. for ($i = 0; $i < $this->m_nColors; $i++) {
  347. $ret .=
  348. chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B
  349. chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G
  350. chr(($this->m_arColors[$i] & 0x000000FF)) . // R
  351. "\x00";
  352. }
  353. return $ret;
  354. }
  355. ///////////////////////////////////////////////////////////////////////////
  356. function colorIndex($rgb)
  357. {
  358. $rgb = intval($rgb) & 0xFFFFFF;
  359. $r1 = ($rgb & 0x0000FF);
  360. $g1 = ($rgb & 0x00FF00) >> 8;
  361. $b1 = ($rgb & 0xFF0000) >> 16;
  362. $idx = -1;
  363. for ($i = 0; $i < $this->m_nColors; $i++) {
  364. $r2 = ($this->m_arColors[$i] & 0x000000FF);
  365. $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8;
  366. $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
  367. $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
  368. if (($idx == -1) || ($d < $dif)) {
  369. $idx = $i;
  370. $dif = $d;
  371. }
  372. }
  373. return $idx;
  374. }
  375. }
  376. ///////////////////////////////////////////////////////////////////////////////////////////////////
  377. class CGIFFILEHEADER
  378. {
  379. var $m_lpVer;
  380. var $m_nWidth;
  381. var $m_nHeight;
  382. var $m_bGlobalClr;
  383. var $m_nColorRes;
  384. var $m_bSorted;
  385. var $m_nTableSize;
  386. var $m_nBgColor;
  387. var $m_nPixelRatio;
  388. var $m_colorTable;
  389. ///////////////////////////////////////////////////////////////////////////
  390. // CONSTRUCTOR
  391. function CGIFFILEHEADER()
  392. {
  393. unSet($this->m_lpVer);
  394. unSet($this->m_nWidth);
  395. unSet($this->m_nHeight);
  396. unSet($this->m_bGlobalClr);
  397. unSet($this->m_nColorRes);
  398. unSet($this->m_bSorted);
  399. unSet($this->m_nTableSize);
  400. unSet($this->m_nBgColor);
  401. unSet($this->m_nPixelRatio);
  402. unSet($this->m_colorTable);
  403. }
  404. ///////////////////////////////////////////////////////////////////////////
  405. function load($lpData, &$hdrLen)
  406. {
  407. $hdrLen = 0;
  408. $this->m_lpVer = substr($lpData, 0, 6);
  409. if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) {
  410. return false;
  411. }
  412. $this->m_nWidth = $this->w2i(substr($lpData, 6, 2));
  413. $this->m_nHeight = $this->w2i(substr($lpData, 8, 2));
  414. if (!$this->m_nWidth || !$this->m_nHeight) {
  415. return false;
  416. }
  417. $b = ord(substr($lpData, 10, 1));
  418. $this->m_bGlobalClr = ($b & 0x80) ? true : false;
  419. $this->m_nColorRes = ($b & 0x70) >> 4;
  420. $this->m_bSorted = ($b & 0x08) ? true : false;
  421. $this->m_nTableSize = 2 << ($b & 0x07);
  422. $this->m_nBgColor = ord(substr($lpData, 11, 1));
  423. $this->m_nPixelRatio = ord(substr($lpData, 12, 1));
  424. $hdrLen = 13;
  425. if ($this->m_bGlobalClr) {
  426. $this->m_colorTable = new CGIFCOLORTABLE();
  427. if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
  428. return false;
  429. }
  430. $hdrLen += 3 * $this->m_nTableSize;
  431. }
  432. return true;
  433. }
  434. ///////////////////////////////////////////////////////////////////////////
  435. function w2i($str)
  436. {
  437. return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
  438. }
  439. }
  440. ///////////////////////////////////////////////////////////////////////////////////////////////////
  441. class CGIFIMAGEHEADER
  442. {
  443. var $m_nLeft;
  444. var $m_nTop;
  445. var $m_nWidth;
  446. var $m_nHeight;
  447. var $m_bLocalClr;
  448. var $m_bInterlace;
  449. var $m_bSorted;
  450. var $m_nTableSize;
  451. var $m_colorTable;
  452. ///////////////////////////////////////////////////////////////////////////
  453. // CONSTRUCTOR
  454. function CGIFIMAGEHEADER()
  455. {
  456. unSet($this->m_nLeft);
  457. unSet($this->m_nTop);
  458. unSet($this->m_nWidth);
  459. unSet($this->m_nHeight);
  460. unSet($this->m_bLocalClr);
  461. unSet($this->m_bInterlace);
  462. unSet($this->m_bSorted);
  463. unSet($this->m_nTableSize);
  464. unSet($this->m_colorTable);
  465. }
  466. ///////////////////////////////////////////////////////////////////////////
  467. function load($lpData, &$hdrLen)
  468. {
  469. $hdrLen = 0;
  470. $this->m_nLeft = $this->w2i(substr($lpData, 0, 2));
  471. $this->m_nTop = $this->w2i(substr($lpData, 2, 2));
  472. $this->m_nWidth = $this->w2i(substr($lpData, 4, 2));
  473. $this->m_nHeight = $this->w2i(substr($lpData, 6, 2));
  474. if (!$this->m_nWidth || !$this->m_nHeight) {
  475. return false;
  476. }
  477. $b = ord($lpData{8});
  478. $this->m_bLocalClr = ($b & 0x80) ? true : false;
  479. $this->m_bInterlace = ($b & 0x40) ? true : false;
  480. $this->m_bSorted = ($b & 0x20) ? true : false;
  481. $this->m_nTableSize = 2 << ($b & 0x07);
  482. $hdrLen = 9;
  483. if ($this->m_bLocalClr) {
  484. $this->m_colorTable = new CGIFCOLORTABLE();
  485. if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
  486. return false;
  487. }
  488. $hdrLen += 3 * $this->m_nTableSize;
  489. }
  490. return true;
  491. }
  492. ///////////////////////////////////////////////////////////////////////////
  493. function w2i($str)
  494. {
  495. return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
  496. }
  497. }
  498. ///////////////////////////////////////////////////////////////////////////////////////////////////
  499. class CGIFIMAGE
  500. {
  501. var $m_disp;
  502. var $m_bUser;
  503. var $m_bTrans;
  504. var $m_nDelay;
  505. var $m_nTrans;
  506. var $m_lpComm;
  507. var $m_gih;
  508. var $m_data;
  509. var $m_lzw;
  510. ///////////////////////////////////////////////////////////////////////////
  511. function CGIFIMAGE()
  512. {
  513. unSet($this->m_disp);
  514. unSet($this->m_bUser);
  515. unSet($this->m_bTrans);
  516. unSet($this->m_nDelay);
  517. unSet($this->m_nTrans);
  518. unSet($this->m_lpComm);
  519. unSet($this->m_data);
  520. $this->m_gih = new CGIFIMAGEHEADER();
  521. $this->m_lzw = new CGIFLZW();
  522. }
  523. ///////////////////////////////////////////////////////////////////////////
  524. function load($data, &$datLen)
  525. {
  526. $datLen = 0;
  527. while (true) {
  528. $b = ord($data{0});
  529. $data = substr($data, 1);
  530. $datLen++;
  531. switch($b) {
  532. case 0x21: // Extension
  533. if (!$this->skipExt($data, $len = 0)) {
  534. return false;
  535. }
  536. $datLen += $len;
  537. break;
  538. case 0x2C: // Image
  539. // LOAD HEADER & COLOR TABLE
  540. if (!$this->m_gih->load($data, $len = 0)) {
  541. return false;
  542. }
  543. $data = substr($data, $len);
  544. $datLen += $len;
  545. // ALLOC BUFFER
  546. if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) {
  547. return false;
  548. }
  549. $data = substr($data, $len);
  550. $datLen += $len;
  551. if ($this->m_gih->m_bInterlace) {
  552. $this->deInterlace();
  553. }
  554. return true;
  555. case 0x3B: // EOF
  556. default:
  557. return false;
  558. }
  559. }
  560. return false;
  561. }
  562. ///////////////////////////////////////////////////////////////////////////
  563. function skipExt(&$data, &$extLen)
  564. {
  565. $extLen = 0;
  566. $b = ord($data{0});
  567. $data = substr($data, 1);
  568. $extLen++;
  569. switch($b) {
  570. case 0xF9: // Graphic Control
  571. $b = ord($data{1});
  572. $this->m_disp = ($b & 0x1C) >> 2;
  573. $this->m_bUser = ($b & 0x02) ? true : false;
  574. $this->m_bTrans = ($b & 0x01) ? true : false;
  575. $this->m_nDelay = $this->w2i(substr($data, 2, 2));
  576. $this->m_nTrans = ord($data{4});
  577. break;
  578. case 0xFE: // Comment
  579. $this->m_lpComm = substr($data, 1, ord($data{0}));
  580. break;
  581. case 0x01: // Plain text
  582. break;
  583. case 0xFF: // Application
  584. break;
  585. }
  586. // SKIP DEFAULT AS DEFS MAY CHANGE
  587. $b = ord($data{0});
  588. $data = substr($data, 1);
  589. $extLen++;
  590. while ($b > 0) {
  591. $data = substr($data, $b);
  592. $extLen += $b;
  593. $b = ord($data{0});
  594. $data = substr($data, 1);
  595. $extLen++;
  596. }
  597. return true;
  598. }
  599. ///////////////////////////////////////////////////////////////////////////
  600. function w2i($str)
  601. {
  602. return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
  603. }
  604. ///////////////////////////////////////////////////////////////////////////
  605. function deInterlace()
  606. {
  607. $data = $this->m_data;
  608. for ($i = 0; $i < 4; $i++) {
  609. switch($i) {
  610. case 0:
  611. $s = 8;
  612. $y = 0;
  613. break;
  614. case 1:
  615. $s = 8;
  616. $y = 4;
  617. break;
  618. case 2:
  619. $s = 4;
  620. $y = 2;
  621. break;
  622. case 3:
  623. $s = 2;
  624. $y = 1;
  625. break;
  626. }
  627. for (; $y < $this->m_gih->m_nHeight; $y += $s) {
  628. $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth);
  629. $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth);
  630. $data =
  631. substr($data, 0, $y * $this->m_gih->m_nWidth) .
  632. $lne .
  633. substr($data, ($y + 1) * $this->m_gih->m_nWidth);
  634. }
  635. }
  636. $this->m_data = $data;
  637. }
  638. }
  639. ///////////////////////////////////////////////////////////////////////////////////////////////////
  640. class CGIF
  641. {
  642. var $m_gfh;
  643. var $m_lpData;
  644. var $m_img;
  645. var $m_bLoaded;
  646. ///////////////////////////////////////////////////////////////////////////
  647. // CONSTRUCTOR
  648. function CGIF()
  649. {
  650. $this->m_gfh = new CGIFFILEHEADER();
  651. $this->m_img = new CGIFIMAGE();
  652. $this->m_lpData = '';
  653. $this->m_bLoaded = false;
  654. }
  655. ///////////////////////////////////////////////////////////////////////////
  656. function loadFile($lpszFileName, $iIndex)
  657. {
  658. if ($iIndex < 0) {
  659. return false;
  660. }
  661. // READ FILE
  662. if (!($fh = @fopen($lpszFileName, 'rb'))) {
  663. return false;
  664. }
  665. $this->m_lpData = @fRead($fh, @fileSize($lpszFileName));
  666. fclose($fh);
  667. // GET FILE HEADER
  668. if (!$this->m_gfh->load($this->m_lpData, $len = 0)) {
  669. return false;
  670. }
  671. $this->m_lpData = substr($this->m_lpData, $len);
  672. do {
  673. if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) {
  674. return false;
  675. }
  676. $this->m_lpData = substr($this->m_lpData, $imgLen);
  677. }
  678. while ($iIndex-- > 0);
  679. $this->m_bLoaded = true;
  680. return true;
  681. }
  682. ///////////////////////////////////////////////////////////////////////////
  683. function getSize($lpszFileName, &$width, &$height)
  684. {
  685. if (!($fh = @fopen($lpszFileName, 'rb'))) {
  686. return false;
  687. }
  688. $data = @fRead($fh, @fileSize($lpszFileName));
  689. @fclose($fh);
  690. $gfh = new CGIFFILEHEADER();
  691. if (!$gfh->load($data, $len = 0)) {
  692. return false;
  693. }
  694. $width = $gfh->m_nWidth;
  695. $height = $gfh->m_nHeight;
  696. return true;
  697. }
  698. ///////////////////////////////////////////////////////////////////////////
  699. function getBmp($bgColor)
  700. {
  701. $out = '';
  702. if (!$this->m_bLoaded) {
  703. return false;
  704. }
  705. // PREPARE COLOR TABLE (RGBQUADs)
  706. if ($this->m_img->m_gih->m_bLocalClr) {
  707. $nColors = $this->m_img->m_gih->m_nTableSize;
  708. $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad();
  709. if ($bgColor != -1) {
  710. $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
  711. }
  712. } elseif ($this->m_gfh->m_bGlobalClr) {
  713. $nColors = $this->m_gfh->m_nTableSize;
  714. $rgbq = $this->m_gfh->m_colorTable->toRGBQuad();
  715. if ($bgColor != -1) {
  716. $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
  717. }
  718. } else {
  719. $nColors = 0;
  720. $bgColor = -1;
  721. }
  722. // PREPARE BITMAP BITS
  723. $data = $this->m_img->m_data;
  724. $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
  725. $bmp = '';
  726. $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0;
  727. for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
  728. for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
  729. if (
  730. ($x >= $this->m_img->m_gih->m_nLeft) &&
  731. ($y >= $this->m_img->m_gih->m_nTop) &&
  732. ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
  733. ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
  734. // PART OF IMAGE
  735. if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
  736. // TRANSPARENT -> BACKGROUND
  737. if ($bgColor == -1) {
  738. $bmp .= chr($this->m_gfh->m_nBgColor);
  739. } else {
  740. $bmp .= chr($bgColor);
  741. }
  742. } else {
  743. $bmp .= $data{$nPxl};
  744. }
  745. } else {
  746. // BACKGROUND
  747. if ($bgColor == -1) {
  748. $bmp .= chr($this->m_gfh->m_nBgColor);
  749. } else {
  750. $bmp .= chr($bgColor);
  751. }
  752. }
  753. }
  754. $nPxl -= $this->m_gfh->m_nWidth << 1;
  755. // ADD PADDING
  756. for ($x = 0; $x < $nPad; $x++) {
  757. $bmp .= "\x00";
  758. }
  759. }
  760. // BITMAPFILEHEADER
  761. $out .= 'BM';
  762. $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp));
  763. $out .= "\x00\x00";
  764. $out .= "\x00\x00";
  765. $out .= $this->dword(14 + 40 + ($nColors << 2));
  766. // BITMAPINFOHEADER
  767. $out .= $this->dword(40);
  768. $out .= $this->dword($this->m_gfh->m_nWidth);
  769. $out .= $this->dword($this->m_gfh->m_nHeight);
  770. $out .= "\x01\x00";
  771. $out .= "\x08\x00";
  772. $out .= "\x00\x00\x00\x00";
  773. $out .= "\x00\x00\x00\x00";
  774. $out .= "\x12\x0B\x00\x00";
  775. $out .= "\x12\x0B\x00\x00";
  776. $out .= $this->dword($nColors % 256);
  777. $out .= "\x00\x00\x00\x00";
  778. // COLOR TABLE
  779. if ($nColors > 0) {
  780. $out .= $rgbq;
  781. }
  782. // DATA
  783. $out .= $bmp;
  784. return $out;
  785. }
  786. ///////////////////////////////////////////////////////////////////////////
  787. function getPng($bgColor)
  788. {
  789. $out = '';
  790. if (!$this->m_bLoaded) {
  791. return false;
  792. }
  793. // PREPARE COLOR TABLE (RGBQUADs)
  794. if ($this->m_img->m_gih->m_bLocalClr) {
  795. $nColors = $this->m_img->m_gih->m_nTableSize;
  796. $pal = $this->m_img->m_gih->m_colorTable->toString();
  797. if ($bgColor != -1) {
  798. $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
  799. }
  800. } elseif ($this->m_gfh->m_bGlobalClr) {
  801. $nColors = $this->m_gfh->m_nTableSize;
  802. $pal = $this->m_gfh->m_colorTable->toString();
  803. if ($bgColor != -1) {
  804. $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
  805. }
  806. } else {
  807. $nColors = 0;
  808. $bgColor = -1;
  809. }
  810. // PREPARE BITMAP BITS
  811. $data = $this->m_img->m_data;
  812. $nPxl = 0;
  813. $bmp = '';
  814. for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
  815. $bmp .= "\x00";
  816. for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
  817. if (
  818. ($x >= $this->m_img->m_gih->m_nLeft) &&
  819. ($y >= $this->m_img->m_gih->m_nTop) &&
  820. ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
  821. ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
  822. // PART OF IMAGE
  823. $bmp .= $data{$nPxl};
  824. } else {
  825. // BACKGROUND
  826. if ($bgColor == -1) {
  827. $bmp .= chr($this->m_gfh->m_nBgColor);
  828. } else {
  829. $bmp .= chr($bgColor);
  830. }
  831. }
  832. }
  833. }
  834. $bmp = gzcompress($bmp, 9);
  835. ///////////////////////////////////////////////////////////////////////
  836. // SIGNATURE
  837. $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
  838. ///////////////////////////////////////////////////////////////////////
  839. // HEADER
  840. $out .= "\x00\x00\x00\x0D";
  841. $tmp = 'IHDR';
  842. $tmp .= $this->ndword($this->m_gfh->m_nWidth);
  843. $tmp .= $this->ndword($this->m_gfh->m_nHeight);
  844. $tmp .= "\x08\x03\x00\x00\x00";
  845. $out .= $tmp;
  846. $out .= $this->ndword(crc32($tmp));
  847. ///////////////////////////////////////////////////////////////////////
  848. // PALETTE
  849. if ($nColors > 0) {
  850. $out .= $this->ndword($nColors * 3);
  851. $tmp = 'PLTE';
  852. $tmp .= $pal;
  853. $out .= $tmp;
  854. $out .= $this->ndword(crc32($tmp));
  855. }
  856. ///////////////////////////////////////////////////////////////////////
  857. // TRANSPARENCY
  858. if (@$this->m_img->m_bTrans && ($nColors > 0)) {
  859. $out .= $this->ndword($nColors);
  860. $tmp = 'tRNS';
  861. for ($i = 0; $i < $nColors; $i++) {
  862. $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF";
  863. }
  864. $out .= $tmp;
  865. $out .= $this->ndword(crc32($tmp));
  866. }
  867. ///////////////////////////////////////////////////////////////////////
  868. // DATA BITS
  869. $out .= $this->ndword(strlen($bmp));
  870. $tmp = 'IDAT';
  871. $tmp .= $bmp;
  872. $out .= $tmp;
  873. $out .= $this->ndword(crc32($tmp));
  874. ///////////////////////////////////////////////////////////////////////
  875. // END OF FILE
  876. $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82";
  877. return $out;
  878. }
  879. ///////////////////////////////////////////////////////////////////////////
  880. // Added by James Heinrich <info@silisoftware.com> - January 5, 2003
  881. // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that
  882. // It's extremely slow, but the only solution when ImageCreateFromString() fails
  883. function getGD_PixelPlotterVersion()
  884. {
  885. if (!$this->m_bLoaded) {
  886. return false;
  887. }
  888. // PREPARE COLOR TABLE (RGBQUADs)
  889. if ($this->m_img->m_gih->m_bLocalClr) {
  890. $pal = $this->m_img->m_gih->m_colorTable->toString();
  891. } elseif ($this->m_gfh->m_bGlobalClr) {
  892. $pal = $this->m_gfh->m_colorTable->toString();
  893. } else {
  894. die('No color table available in getGD_PixelPlotterVersion()');
  895. }
  896. $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight);
  897. $NumColorsInPal = floor(strlen($pal) / 3);
  898. for ($i = 0; $i < $NumColorsInPal; $i++) {
  899. $ThisImageColor[$i] = ImageColorAllocate(
  900. $PlottingIMG,
  901. ord($pal{(($i * 3) + 0)}),
  902. ord($pal{(($i * 3) + 1)}),
  903. ord($pal{(($i * 3) + 2)}));
  904. }
  905. // PREPARE BITMAP BITS
  906. $data = $this->m_img->m_data;
  907. $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
  908. for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
  909. if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
  910. set_time_limit(30);
  911. }
  912. for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
  913. if (
  914. ($x >= $this->m_img->m_gih->m_nLeft) &&
  915. ($y >= $this->m_img->m_gih->m_nTop) &&
  916. ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
  917. ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
  918. // PART OF IMAGE
  919. if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
  920. ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
  921. } else {
  922. ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]);
  923. }
  924. } else {
  925. // BACKGROUND
  926. ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
  927. }
  928. }
  929. $nPxl -= $this->m_gfh->m_nWidth << 1;
  930. }
  931. return $PlottingIMG;
  932. }
  933. ///////////////////////////////////////////////////////////////////////////
  934. function dword($val)
  935. {
  936. $val = intval($val);
  937. return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24);
  938. }
  939. ///////////////////////////////////////////////////////////////////////////
  940. function ndword($val)
  941. {
  942. $val = intval($val);
  943. return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF);
  944. }
  945. ///////////////////////////////////////////////////////////////////////////
  946. function width()
  947. {
  948. return $this->m_gfh->m_nWidth;
  949. }
  950. ///////////////////////////////////////////////////////////////////////////
  951. function height()
  952. {
  953. return $this->m_gfh->m_nHeight;
  954. }
  955. ///////////////////////////////////////////////////////////////////////////
  956. function comment()
  957. {
  958. return $this->m_img->m_lpComm;
  959. }
  960. ///////////////////////////////////////////////////////////////////////////
  961. function loaded()
  962. {
  963. return $this->m_bLoaded;
  964. }
  965. }
  966. ///////////////////////////////////////////////////////////////////////////////////////////////////
  967. ?>