XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
phpthumb.gif.php
Go to the documentation of this file.
1 <?php
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.
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
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
23 
24 function gif_loadFile($lpszFileName, $iIndex = 0)
25 {
26  $gif = new CGIF();
27  if ($gif->loadFile($lpszFileName, $iIndex)) {
28  return $gif;
29  }
30  return false;
31 }
32 
34 
35 // Added by James Heinrich <info@silisoftware.com> - December 10, 2003
36 function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1)
37 {
38  if ($gif = gif_loadFile($gifFilename)) {
39 
40  if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
41  // shouldn't take nearly this long
42  set_time_limit(120);
43  }
44  // general strategy: convert raw data to PNG then convert PNG data to GD image resource
45  $PNGdata = $gif->getPng($bgColor);
46  if ($img = @ImageCreateFromString($PNGdata)) {
47 
48  // excellent - PNG image data successfully converted to GD image
49  return $img;
50 
51  } elseif ($img = $gif->getGD_PixelPlotterVersion()) {
52 
53  // problem: ImageCreateFromString() didn't like the PNG image data.
54  // This has been known to happen in PHP v4.0.6
55  // solution: take the raw image data and create a new GD image and plot
56  // pixel-by-pixel on the GD image. This is extremely slow, but it does
57  // work and a slow solution is better than no solution, right? :)
58  return $img;
59 
60  }
61  }
62  return false;
63 }
64 
66 
67 function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1)
68 {
69  if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
70  return false;
71  }
72 
73  $fd = $gif->getBmp($bgColor);
74  if (strlen($fd) <= 0) {
75  return false;
76  }
77 
78  if (!($fh = @fopen($lpszFileName, 'wb'))) {
79  return false;
80  }
81  @fwrite($fh, $fd, strlen($fd));
82  @fflush($fh);
83  @fclose($fh);
84  return true;
85 }
86 
88 
89 function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1)
90 {
91  if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
92  return false;
93  }
94 
95  $fd = $gif->getPng($bgColor);
96  if (strlen($fd) <= 0) {
97  return false;
98  }
99 
100  if (!($fh = @fopen($lpszFileName, 'wb'))) {
101  return false;
102  }
103  @fwrite($fh, $fd, strlen($fd));
104  @fflush($fh);
105  @fclose($fh);
106  return true;
107 }
108 
110 
111 function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1)
112 {
113  // JPEG output that does not require cjpeg added by James Heinrich <info@silisoftware.com> - December 10, 2003
114  if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) {
115 
116  if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) {
117  exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null');
118  @unLink($lpszFileName.'.bmp');
119 
120  if (@file_exists($lpszFileName)) {
121  if (@fileSize($lpszFileName) > 0) {
122  return true;
123  }
124 
125  @unLink($lpszFileName);
126  }
127  }
128 
129  } else {
130 
131  // either Windows, or cjpeg not found in path
132  if ($img = @ImageCreateFromString($gif->getPng($bgColor))) {
133  if (@ImageJPEG($img, $lpszFileName)) {
134  return true;
135  }
136  }
137 
138  }
139 
140  return false;
141 }
142 
144 
145 function gif_getSize($gif, &$width, &$height)
146 {
147  if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) {
148  $width = $gif->width();
149  $height = $gif->height();
150  } elseif (@file_exists($gif)) {
151  $myGIF = new CGIF();
152  if (!$myGIF->getSize($gif, $width, $height)) {
153  return false;
154  }
155  } else {
156  return false;
157  }
158 
159  return true;
160 }
161 
163 
164 class CGIFLZW
165 {
169 
171 
172  // CONSTRUCTOR
173  function CGIFLZW()
174  {
175  $this->MAX_LZW_BITS = 12;
176  unSet($this->Next);
177  unSet($this->Vals);
178  unSet($this->Stack);
179  unSet($this->Buf);
180 
181  $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1);
182  $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1);
183  $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
184  $this->Buf = range(0, 279);
185  }
186 
188 
189  function deCompress($data, &$datLen)
190  {
191  $stLen = strlen($data);
192  $datLen = 0;
193  $ret = '';
194 
195  // INITIALIZATION
196  $this->LZWCommand($data, true);
197 
198  while (($iIndex = $this->LZWCommand($data, false)) >= 0) {
199  $ret .= chr($iIndex);
200  }
201 
202  $datLen = $stLen - strlen($data);
203 
204  if ($iIndex != -2) {
205  return false;
206  }
207 
208  return $ret;
209  }
210 
212 
213  function LZWCommand(&$data, $bInit)
214  {
215  if ($bInit) {
216  $this->SetCodeSize = ord($data{0});
217  $data = substr($data, 1);
218 
219  $this->CodeSize = $this->SetCodeSize + 1;
220  $this->ClearCode = 1 << $this->SetCodeSize;
221  $this->EndCode = $this->ClearCode + 1;
222  $this->MaxCode = $this->ClearCode + 2;
223  $this->MaxCodeSize = $this->ClearCode << 1;
224 
225  $this->GetCode($data, $bInit);
226 
227  $this->Fresh = 1;
228  for ($i = 0; $i < $this->ClearCode; $i++) {
229  $this->Next[$i] = 0;
230  $this->Vals[$i] = $i;
231  }
232 
233  for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
234  $this->Next[$i] = 0;
235  $this->Vals[$i] = 0;
236  }
237 
238  $this->sp = 0;
239  return 1;
240  }
241 
242  if ($this->Fresh) {
243  $this->Fresh = 0;
244  do {
245  $this->FirstCode = $this->GetCode($data, $bInit);
246  $this->OldCode = $this->FirstCode;
247  }
248  while ($this->FirstCode == $this->ClearCode);
249 
250  return $this->FirstCode;
251  }
252 
253  if ($this->sp > 0) {
254  $this->sp--;
255  return $this->Stack[$this->sp];
256  }
257 
258  while (($Code = $this->GetCode($data, $bInit)) >= 0) {
259  if ($Code == $this->ClearCode) {
260  for ($i = 0; $i < $this->ClearCode; $i++) {
261  $this->Next[$i] = 0;
262  $this->Vals[$i] = $i;
263  }
264 
265  for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
266  $this->Next[$i] = 0;
267  $this->Vals[$i] = 0;
268  }
269 
270  $this->CodeSize = $this->SetCodeSize + 1;
271  $this->MaxCodeSize = $this->ClearCode << 1;
272  $this->MaxCode = $this->ClearCode + 2;
273  $this->sp = 0;
274  $this->FirstCode = $this->GetCode($data, $bInit);
275  $this->OldCode = $this->FirstCode;
276 
277  return $this->FirstCode;
278  }
279 
280  if ($Code == $this->EndCode) {
281  return -2;
282  }
283 
284  $InCode = $Code;
285  if ($Code >= $this->MaxCode) {
286  $this->Stack[$this->sp] = $this->FirstCode;
287  $this->sp++;
288  $Code = $this->OldCode;
289  }
290 
291  while ($Code >= $this->ClearCode) {
292  $this->Stack[$this->sp] = $this->Vals[$Code];
293  $this->sp++;
294 
295  if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
296  return -1;
297 
298  $Code = $this->Next[$Code];
299  }
300 
301  $this->FirstCode = $this->Vals[$Code];
302  $this->Stack[$this->sp] = $this->FirstCode;
303  $this->sp++;
304 
305  if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) {
306  $this->Next[$Code] = $this->OldCode;
307  $this->Vals[$Code] = $this->FirstCode;
308  $this->MaxCode++;
309 
310  if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) {
311  $this->MaxCodeSize *= 2;
312  $this->CodeSize++;
313  }
314  }
315 
316  $this->OldCode = $InCode;
317  if ($this->sp > 0) {
318  $this->sp--;
319  return $this->Stack[$this->sp];
320  }
321  }
322 
323  return $Code;
324  }
325 
327 
328  function GetCode(&$data, $bInit)
329  {
330  if ($bInit) {
331  $this->CurBit = 0;
332  $this->LastBit = 0;
333  $this->Done = 0;
334  $this->LastByte = 2;
335  return 1;
336  }
337 
338  if (($this->CurBit + $this->CodeSize) >= $this->LastBit) {
339  if ($this->Done) {
340  if ($this->CurBit >= $this->LastBit) {
341  // Ran off the end of my bits
342  return 0;
343  }
344  return -1;
345  }
346 
347  $this->Buf[0] = $this->Buf[$this->LastByte - 2];
348  $this->Buf[1] = $this->Buf[$this->LastByte - 1];
349 
350  $Count = ord($data{0});
351  $data = substr($data, 1);
352 
353  if ($Count) {
354  for ($i = 0; $i < $Count; $i++) {
355  $this->Buf[2 + $i] = ord($data{$i});
356  }
357  $data = substr($data, $Count);
358  } else {
359  $this->Done = 1;
360  }
361 
362  $this->LastByte = 2 + $Count;
363  $this->CurBit = ($this->CurBit - $this->LastBit) + 16;
364  $this->LastBit = (2 + $Count) << 3;
365  }
366 
367  $iRet = 0;
368  for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) {
369  $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
370  }
371 
372  $this->CurBit += $this->CodeSize;
373  return $iRet;
374  }
375 }
376 
378 
380 {
383 
385 
386  // CONSTRUCTOR
387  function CGIFCOLORTABLE()
388  {
389  unSet($this->m_nColors);
390  unSet($this->m_arColors);
391  }
392 
394 
395  function load($lpData, $num)
396  {
397  $this->m_nColors = 0;
398  $this->m_arColors = array();
399 
400  for ($i = 0; $i < $num; $i++) {
401  $rgb = substr($lpData, $i * 3, 3);
402  if (strlen($rgb) < 3) {
403  return false;
404  }
405 
406  $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0});
407  $this->m_nColors++;
408  }
409 
410  return true;
411  }
412 
414 
415  function toString()
416  {
417  $ret = '';
418 
419  for ($i = 0; $i < $this->m_nColors; $i++) {
420  $ret .=
421  chr(($this->m_arColors[$i] & 0x000000FF)) . // R
422  chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G
423  chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B
424  }
425 
426  return $ret;
427  }
428 
430 
431  function toRGBQuad()
432  {
433  $ret = '';
434 
435  for ($i = 0; $i < $this->m_nColors; $i++) {
436  $ret .=
437  chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B
438  chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G
439  chr(($this->m_arColors[$i] & 0x000000FF)) . // R
440  "\x00";
441  }
442 
443  return $ret;
444  }
445 
447 
448  function colorIndex($rgb)
449  {
450  $rgb = intval($rgb) & 0xFFFFFF;
451  $r1 = ($rgb & 0x0000FF);
452  $g1 = ($rgb & 0x00FF00) >> 8;
453  $b1 = ($rgb & 0xFF0000) >> 16;
454  $idx = -1;
455 
456  for ($i = 0; $i < $this->m_nColors; $i++) {
457  $r2 = ($this->m_arColors[$i] & 0x000000FF);
458  $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8;
459  $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
460  $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
461 
462  if (($idx == -1) || ($d < $dif)) {
463  $idx = $i;
464  $dif = $d;
465  }
466  }
467 
468  return $idx;
469  }
470 }
471 
473 
475 {
476  var $m_lpVer;
486 
488 
489  // CONSTRUCTOR
490  function CGIFFILEHEADER()
491  {
492  unSet($this->m_lpVer);
493  unSet($this->m_nWidth);
494  unSet($this->m_nHeight);
495  unSet($this->m_bGlobalClr);
496  unSet($this->m_nColorRes);
497  unSet($this->m_bSorted);
498  unSet($this->m_nTableSize);
499  unSet($this->m_nBgColor);
500  unSet($this->m_nPixelRatio);
501  unSet($this->m_colorTable);
502  }
503 
505 
506  function load($lpData, &$hdrLen)
507  {
508  $hdrLen = 0;
509 
510  $this->m_lpVer = substr($lpData, 0, 6);
511  if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) {
512  return false;
513  }
514 
515  $this->m_nWidth = $this->w2i(substr($lpData, 6, 2));
516  $this->m_nHeight = $this->w2i(substr($lpData, 8, 2));
517  if (!$this->m_nWidth || !$this->m_nHeight) {
518  return false;
519  }
520 
521  $b = ord(substr($lpData, 10, 1));
522  $this->m_bGlobalClr = ($b & 0x80) ? true : false;
523  $this->m_nColorRes = ($b & 0x70) >> 4;
524  $this->m_bSorted = ($b & 0x08) ? true : false;
525  $this->m_nTableSize = 2 << ($b & 0x07);
526  $this->m_nBgColor = ord(substr($lpData, 11, 1));
527  $this->m_nPixelRatio = ord(substr($lpData, 12, 1));
528  $hdrLen = 13;
529 
530  if ($this->m_bGlobalClr) {
531  $this->m_colorTable = new CGIFCOLORTABLE();
532  if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
533  return false;
534  }
535  $hdrLen += 3 * $this->m_nTableSize;
536  }
537 
538  return true;
539  }
540 
542 
543  function w2i($str)
544  {
545  return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
546  }
547 }
548 
550 
552 {
553  var $m_nLeft;
554  var $m_nTop;
562 
564 
565  // CONSTRUCTOR
566  function CGIFIMAGEHEADER()
567  {
568  unSet($this->m_nLeft);
569  unSet($this->m_nTop);
570  unSet($this->m_nWidth);
571  unSet($this->m_nHeight);
572  unSet($this->m_bLocalClr);
573  unSet($this->m_bInterlace);
574  unSet($this->m_bSorted);
575  unSet($this->m_nTableSize);
576  unSet($this->m_colorTable);
577  }
578 
580 
581  function load($lpData, &$hdrLen)
582  {
583  $hdrLen = 0;
584 
585  $this->m_nLeft = $this->w2i(substr($lpData, 0, 2));
586  $this->m_nTop = $this->w2i(substr($lpData, 2, 2));
587  $this->m_nWidth = $this->w2i(substr($lpData, 4, 2));
588  $this->m_nHeight = $this->w2i(substr($lpData, 6, 2));
589 
590  if (!$this->m_nWidth || !$this->m_nHeight) {
591  return false;
592  }
593 
594  $b = ord($lpData{8});
595  $this->m_bLocalClr = ($b & 0x80) ? true : false;
596  $this->m_bInterlace = ($b & 0x40) ? true : false;
597  $this->m_bSorted = ($b & 0x20) ? true : false;
598  $this->m_nTableSize = 2 << ($b & 0x07);
599  $hdrLen = 9;
600 
601  if ($this->m_bLocalClr) {
602  $this->m_colorTable = new CGIFCOLORTABLE();
603  if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
604  return false;
605  }
606  $hdrLen += 3 * $this->m_nTableSize;
607  }
608 
609  return true;
610  }
611 
613 
614  function w2i($str)
615  {
616  return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
617  }
618 }
619 
621 
623 {
624  var $m_disp;
625  var $m_bUser;
630  var $m_gih;
631  var $m_data;
632  var $m_lzw;
633 
635 
636  function CGIFIMAGE()
637  {
638  unSet($this->m_disp);
639  unSet($this->m_bUser);
640  unSet($this->m_bTrans);
641  unSet($this->m_nDelay);
642  unSet($this->m_nTrans);
643  unSet($this->m_lpComm);
644  unSet($this->m_data);
645  $this->m_gih = new CGIFIMAGEHEADER();
646  $this->m_lzw = new CGIFLZW();
647  }
648 
650 
651  function load($data, &$datLen)
652  {
653  $datLen = 0;
654 
655  while (true) {
656  $b = ord($data{0});
657  $data = substr($data, 1);
658  $datLen++;
659 
660  switch($b) {
661  case 0x21: // Extension
662  if (!$this->skipExt($data, $len = 0)) {
663  return false;
664  }
665  $datLen += $len;
666  break;
667 
668  case 0x2C: // Image
669  // LOAD HEADER & COLOR TABLE
670  if (!$this->m_gih->load($data, $len = 0)) {
671  return false;
672  }
673  $data = substr($data, $len);
674  $datLen += $len;
675 
676  // ALLOC BUFFER
677  if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) {
678  return false;
679  }
680  $data = substr($data, $len);
681  $datLen += $len;
682 
683  if ($this->m_gih->m_bInterlace) {
684  $this->deInterlace();
685  }
686  return true;
687 
688  case 0x3B: // EOF
689  default:
690  return false;
691  }
692  }
693  return false;
694  }
695 
697 
698  function skipExt(&$data, &$extLen)
699  {
700  $extLen = 0;
701 
702  $b = ord($data{0});
703  $data = substr($data, 1);
704  $extLen++;
705 
706  switch($b) {
707  case 0xF9: // Graphic Control
708  $b = ord($data{1});
709  $this->m_disp = ($b & 0x1C) >> 2;
710  $this->m_bUser = ($b & 0x02) ? true : false;
711  $this->m_bTrans = ($b & 0x01) ? true : false;
712  $this->m_nDelay = $this->w2i(substr($data, 2, 2));
713  $this->m_nTrans = ord($data{4});
714  break;
715 
716  case 0xFE: // Comment
717  $this->m_lpComm = substr($data, 1, ord($data{0}));
718  break;
719 
720  case 0x01: // Plain text
721  break;
722 
723  case 0xFF: // Application
724  break;
725  }
726 
727  // SKIP DEFAULT AS DEFS MAY CHANGE
728  $b = ord($data{0});
729  $data = substr($data, 1);
730  $extLen++;
731  while ($b > 0) {
732  $data = substr($data, $b);
733  $extLen += $b;
734  $b = ord($data{0});
735  $data = substr($data, 1);
736  $extLen++;
737  }
738  return true;
739  }
740 
742 
743  function w2i($str)
744  {
745  return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
746  }
747 
749 
750  function deInterlace()
751  {
752  $data = $this->m_data;
753 
754  for ($i = 0; $i < 4; $i++) {
755  switch($i) {
756  case 0:
757  $s = 8;
758  $y = 0;
759  break;
760 
761  case 1:
762  $s = 8;
763  $y = 4;
764  break;
765 
766  case 2:
767  $s = 4;
768  $y = 2;
769  break;
770 
771  case 3:
772  $s = 2;
773  $y = 1;
774  break;
775  }
776 
777  for (; $y < $this->m_gih->m_nHeight; $y += $s) {
778  $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth);
779  $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth);
780 
781  $data =
782  substr($data, 0, $y * $this->m_gih->m_nWidth) .
783  $lne .
784  substr($data, ($y + 1) * $this->m_gih->m_nWidth);
785  }
786  }
787 
788  $this->m_data = $data;
789  }
790 }
791 
793 
794 class CGIF
795 {
796  var $m_gfh;
798  var $m_img;
800 
802 
803  // CONSTRUCTOR
804  function CGIF()
805  {
806  $this->m_gfh = new CGIFFILEHEADER();
807  $this->m_img = new CGIFIMAGE();
808  $this->m_lpData = '';
809  $this->m_bLoaded = false;
810  }
811 
813 
814  function loadFile($lpszFileName, $iIndex)
815  {
816  if ($iIndex < 0) {
817  return false;
818  }
819 
820  // READ FILE
821  if (!($fh = @fopen($lpszFileName, 'rb'))) {
822  return false;
823  }
824  $this->m_lpData = @fRead($fh, @fileSize($lpszFileName));
825  fclose($fh);
826 
827  // GET FILE HEADER
828  if (!$this->m_gfh->load($this->m_lpData, $len = 0)) {
829  return false;
830  }
831  $this->m_lpData = substr($this->m_lpData, $len);
832 
833  do {
834  if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) {
835  return false;
836  }
837  $this->m_lpData = substr($this->m_lpData, $imgLen);
838  }
839  while ($iIndex-- > 0);
840 
841  $this->m_bLoaded = true;
842  return true;
843  }
844 
846 
847  function getSize($lpszFileName, &$width, &$height)
848  {
849  if (!($fh = @fopen($lpszFileName, 'rb'))) {
850  return false;
851  }
852  $data = @fRead($fh, @fileSize($lpszFileName));
853  @fclose($fh);
854 
855  $gfh = new CGIFFILEHEADER();
856  if (!$gfh->load($data, $len = 0)) {
857  return false;
858  }
859 
860  $width = $gfh->m_nWidth;
861  $height = $gfh->m_nHeight;
862  return true;
863  }
864 
866 
867  function getBmp($bgColor)
868  {
869  $out = '';
870 
871  if (!$this->m_bLoaded) {
872  return false;
873  }
874 
875  // PREPARE COLOR TABLE (RGBQUADs)
876  if ($this->m_img->m_gih->m_bLocalClr) {
877  $nColors = $this->m_img->m_gih->m_nTableSize;
878  $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad();
879  if ($bgColor != -1) {
880  $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
881  }
882  } elseif ($this->m_gfh->m_bGlobalClr) {
883  $nColors = $this->m_gfh->m_nTableSize;
884  $rgbq = $this->m_gfh->m_colorTable->toRGBQuad();
885  if ($bgColor != -1) {
886  $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
887  }
888  } else {
889  $nColors = 0;
890  $bgColor = -1;
891  }
892 
893  // PREPARE BITMAP BITS
894  $data = $this->m_img->m_data;
895  $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
896  $bmp = '';
897  $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0;
898  for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
899  for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
900  if (
901  ($x >= $this->m_img->m_gih->m_nLeft) &&
902  ($y >= $this->m_img->m_gih->m_nTop) &&
903  ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
904  ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
905  // PART OF IMAGE
906  if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
907  // TRANSPARENT -> BACKGROUND
908  if ($bgColor == -1) {
909  $bmp .= chr($this->m_gfh->m_nBgColor);
910  } else {
911  $bmp .= chr($bgColor);
912  }
913  } else {
914  $bmp .= $data{$nPxl};
915  }
916  } else {
917  // BACKGROUND
918  if ($bgColor == -1) {
919  $bmp .= chr($this->m_gfh->m_nBgColor);
920  } else {
921  $bmp .= chr($bgColor);
922  }
923  }
924  }
925  $nPxl -= $this->m_gfh->m_nWidth << 1;
926 
927  // ADD PADDING
928  for ($x = 0; $x < $nPad; $x++) {
929  $bmp .= "\x00";
930  }
931  }
932 
933  // BITMAPFILEHEADER
934  $out .= 'BM';
935  $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp));
936  $out .= "\x00\x00";
937  $out .= "\x00\x00";
938  $out .= $this->dword(14 + 40 + ($nColors << 2));
939 
940  // BITMAPINFOHEADER
941  $out .= $this->dword(40);
942  $out .= $this->dword($this->m_gfh->m_nWidth);
943  $out .= $this->dword($this->m_gfh->m_nHeight);
944  $out .= "\x01\x00";
945  $out .= "\x08\x00";
946  $out .= "\x00\x00\x00\x00";
947  $out .= "\x00\x00\x00\x00";
948  $out .= "\x12\x0B\x00\x00";
949  $out .= "\x12\x0B\x00\x00";
950  $out .= $this->dword($nColors % 256);
951  $out .= "\x00\x00\x00\x00";
952 
953  // COLOR TABLE
954  if ($nColors > 0) {
955  $out .= $rgbq;
956  }
957 
958  // DATA
959  $out .= $bmp;
960 
961  return $out;
962  }
963 
965 
966  function getPng($bgColor)
967  {
968  $out = '';
969 
970  if (!$this->m_bLoaded) {
971  return false;
972  }
973 
974  // PREPARE COLOR TABLE (RGBQUADs)
975  if ($this->m_img->m_gih->m_bLocalClr) {
976  $nColors = $this->m_img->m_gih->m_nTableSize;
977  $pal = $this->m_img->m_gih->m_colorTable->toString();
978  if ($bgColor != -1) {
979  $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
980  }
981  } elseif ($this->m_gfh->m_bGlobalClr) {
982  $nColors = $this->m_gfh->m_nTableSize;
983  $pal = $this->m_gfh->m_colorTable->toString();
984  if ($bgColor != -1) {
985  $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
986  }
987  } else {
988  $nColors = 0;
989  $bgColor = -1;
990  }
991 
992  // PREPARE BITMAP BITS
993  $data = $this->m_img->m_data;
994  $nPxl = 0;
995  $bmp = '';
996  for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
997  $bmp .= "\x00";
998  for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
999  if (
1000  ($x >= $this->m_img->m_gih->m_nLeft) &&
1001  ($y >= $this->m_img->m_gih->m_nTop) &&
1002  ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
1003  ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
1004  // PART OF IMAGE
1005  $bmp .= $data{$nPxl};
1006  } else {
1007  // BACKGROUND
1008  if ($bgColor == -1) {
1009  $bmp .= chr($this->m_gfh->m_nBgColor);
1010  } else {
1011  $bmp .= chr($bgColor);
1012  }
1013  }
1014  }
1015  }
1016  $bmp = gzcompress($bmp, 9);
1017 
1019  // SIGNATURE
1020  $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
1022  // HEADER
1023  $out .= "\x00\x00\x00\x0D";
1024  $tmp = 'IHDR';
1025  $tmp .= $this->ndword($this->m_gfh->m_nWidth);
1026  $tmp .= $this->ndword($this->m_gfh->m_nHeight);
1027  $tmp .= "\x08\x03\x00\x00\x00";
1028  $out .= $tmp;
1029  $out .= $this->ndword(crc32($tmp));
1031  // PALETTE
1032  if ($nColors > 0) {
1033  $out .= $this->ndword($nColors * 3);
1034  $tmp = 'PLTE';
1035  $tmp .= $pal;
1036  $out .= $tmp;
1037  $out .= $this->ndword(crc32($tmp));
1038  }
1040  // TRANSPARENCY
1041  if (@$this->m_img->m_bTrans && ($nColors > 0)) {
1042  $out .= $this->ndword($nColors);
1043  $tmp = 'tRNS';
1044  for ($i = 0; $i < $nColors; $i++) {
1045  $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF";
1046  }
1047  $out .= $tmp;
1048  $out .= $this->ndword(crc32($tmp));
1049  }
1051  // DATA BITS
1052  $out .= $this->ndword(strlen($bmp));
1053  $tmp = 'IDAT';
1054  $tmp .= $bmp;
1055  $out .= $tmp;
1056  $out .= $this->ndword(crc32($tmp));
1058  // END OF FILE
1059  $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82";
1060 
1061  return $out;
1062  }
1063 
1065 
1066  // Added by James Heinrich <info@silisoftware.com> - January 5, 2003
1067 
1068  // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that
1069  // It's extremely slow, but the only solution when ImageCreateFromString() fails
1071  {
1072  if (!$this->m_bLoaded) {
1073  return false;
1074  }
1075 
1076  // PREPARE COLOR TABLE (RGBQUADs)
1077  if ($this->m_img->m_gih->m_bLocalClr) {
1078  $pal = $this->m_img->m_gih->m_colorTable->toString();
1079  } elseif ($this->m_gfh->m_bGlobalClr) {
1080  $pal = $this->m_gfh->m_colorTable->toString();
1081  } else {
1082  die('No color table available in getGD_PixelPlotterVersion()');
1083  }
1084 
1085  $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight);
1086  $NumColorsInPal = floor(strlen($pal) / 3);
1087  for ($i = 0; $i < $NumColorsInPal; $i++) {
1088  $ThisImageColor[$i] = ImageColorAllocate(
1089  $PlottingIMG,
1090  ord($pal{(($i * 3) + 0)}),
1091  ord($pal{(($i * 3) + 1)}),
1092  ord($pal{(($i * 3) + 2)}));
1093  }
1094 
1095  // PREPARE BITMAP BITS
1096  $data = $this->m_img->m_data;
1097  $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
1098  for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
1099  if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
1100  set_time_limit(30);
1101  }
1102  for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
1103  if (
1104  ($x >= $this->m_img->m_gih->m_nLeft) &&
1105  ($y >= $this->m_img->m_gih->m_nTop) &&
1106  ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
1107  ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) {
1108  // PART OF IMAGE
1109  if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
1110  ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
1111  } else {
1112  ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]);
1113  }
1114  } else {
1115  // BACKGROUND
1116  ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
1117  }
1118  }
1119  $nPxl -= $this->m_gfh->m_nWidth << 1;
1120 
1121  }
1122 
1123  return $PlottingIMG;
1124  }
1125 
1127 
1128  function dword($val)
1129  {
1130  $val = intval($val);
1131  return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24);
1132  }
1133 
1135 
1136  function ndword($val)
1137  {
1138  $val = intval($val);
1139  return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF);
1140  }
1141 
1143 
1144  function width()
1145  {
1146  return $this->m_gfh->m_nWidth;
1147  }
1148 
1150 
1151  function height()
1152  {
1153  return $this->m_gfh->m_nHeight;
1154  }
1155 
1157 
1158  function comment()
1159  {
1160  return $this->m_img->m_lpComm;
1161  }
1162 
1164 
1165  function loaded()
1166  {
1167  return $this->m_bLoaded;
1168  }
1169 }
1170 
1172 
1173 ?>