root/devel/lib/phpthumb/phpthumb.gif.php

Revision 421, 29.0 kB (checked in by sven, 3 years ago)

icons: upgrade phpthumb to 1.7.2 and move it to lib/
change icons to be output through a function rather than the bundled phpThumb.php, to allow greater control over security

  • Property svn:eol-style set to native
Line 
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
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
33 ///////////////////////////////////////////////////////////////////////////////////////////////////
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         @set_time_limit(300);
41         // general strategy: convert raw data to PNG then convert PNG data to GD image resource
42         $PNGdata = $gif->getPng($bgColor);
43         if ($img = @ImageCreateFromString($PNGdata)) {
44
45             // excellent - PNG image data successfully converted to GD image
46             return $img;
47
48         } elseif ($img = $gif->getGD_PixelPlotterVersion()) {
49
50             // problem: ImageCreateFromString() didn't like the PNG image data.
51             //   This has been known to happen in PHP v4.0.6
52             // solution: take the raw image data and create a new GD image and plot
53             //   pixel-by-pixel on the GD image. This is extremely slow, but it does
54             //   work and a slow solution is better than no solution, right? :)
55             return $img;
56
57         }
58     }
59     return false;
60 }
61
62 ///////////////////////////////////////////////////////////////////////////////////////////////////
63
64 function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1)
65 {
66     if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
67         return false;
68     }
69
70     $fd = $gif->getBmp($bgColor);
71     if (strlen($fd) <= 0) {
72         return false;
73     }
74
75     if (!($fh = @fopen($lpszFileName, 'wb'))) {
76         return false;
77     }
78     @fwrite($fh, $fd, strlen($fd));
79     @fflush($fh);
80     @fclose($fh);
81     return true;
82 }
83
84 ///////////////////////////////////////////////////////////////////////////////////////////////////
85
86 function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1)
87 {
88     if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
89         return false;
90     }
91
92     $fd = $gif->getPng($bgColor);
93     if (strlen($fd) <= 0) {
94         return false;
95     }
96
97     if (!($fh = @fopen($lpszFileName, 'wb'))) {
98         return false;
99     }
100     @fwrite($fh, $fd, strlen($fd));
101     @fflush($fh);
102     @fclose($fh);
103     return true;
104 }
105
106 ///////////////////////////////////////////////////////////////////////////////////////////////////
107
108 function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1)
109 {
110     // JPEG output that does not require cjpeg added by James Heinrich <info@silisoftware.com> - December 10, 2003
111     if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) {
112
113         if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) {
114             exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null');
115             @unLink($lpszFileName.'.bmp');
116
117             if (@file_exists($lpszFileName)) {
118                 if (@fileSize($lpszFileName) > 0) {
119                     return true;
120                 }
121
122                 @unLink($lpszFileName);
123             }
124         }
125
126     } else {
127
128         // either Windows, or cjpeg not found in path
129         if ($img = @ImageCreateFromString($gif->getPng($bgColor))) {
130             if (@ImageJPEG($img, $lpszFileName)) {
131                 return true;
132             }
133         }
134
135     }
136
137     return false;
138 }
139
140 ///////////////////////////////////////////////////////////////////////////////////////////////////
141
142 function gif_getSize($gif, &$width, &$height)
143 {
144     if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) {
145         $width  = $gif->width();
146         $height = $gif->height();
147     } elseif (@file_exists($gif)) {
148         $myGIF = new CGIF();
149         if (!$myGIF->getSize($gif, $width, $height)) {
150             return false;
151         }
152     } else {
153         return false;
154     }
155
156     return true;
157 }
158
159 ///////////////////////////////////////////////////////////////////////////////////////////////////
160
161 class CGIFLZW
162 {
163     var $MAX_LZW_BITS;
164     var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
165     var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
166
167     ///////////////////////////////////////////////////////////////////////////
168
169     // CONSTRUCTOR
170     function CGIFLZW()
171     {
172         $this->MAX_LZW_BITS = 12;
173         unSet($this->Next);
174         unSet($this->Vals);
175         unSet($this->Stack);
176         unSet($this->Buf);
177
178         $this->Next  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
179         $this->Vals  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
180         $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
181         $this->Buf   = range(0, 279);
182     }
183
184     ///////////////////////////////////////////////////////////////////////////
185
186     function deCompress($data, &$datLen)
187     {
188         $stLen  = strlen($data);
189         $datLen = 0;
190         $ret    = '';
191
192         // INITIALIZATION
193         $this->LZWCommand($data, true);
194
195         while (($iIndex = $this->LZWCommand($data, false)) >= 0) {
196             $ret .= chr($iIndex);
197         }
198
199         $datLen = $stLen - strlen($data);
200
201         if ($iIndex != -2) {
202             return false;
203         }
204
205         return $ret;
206     }
207
208     ///////////////////////////////////////////////////////////////////////////
209
210     function LZWCommand(&$data, $bInit)
211     {
212         if ($bInit) {
213             $this->SetCodeSize = ord($data{0});
214             $data = substr($data, 1);
215
216             $this->CodeSize    = $this->SetCodeSize + 1;
217             $this->ClearCode   = 1 << $this->SetCodeSize;
218             $this->EndCode     = $this->ClearCode + 1;
219             $this->MaxCode     = $this->ClearCode + 2;
220             $this->MaxCodeSize = $this->ClearCode << 1;
221
222             $this->GetCode($data, $bInit);
223
224             $this->Fresh = 1;
225             for ($i = 0; $i < $this->ClearCode; $i++) {
226                 $this->Next[$i] = 0;
227                 $this->Vals[$i] = $i;
228             }
229
230             for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
231                 $this->Next[$i] = 0;
232                 $this->Vals[$i] = 0;
233             }
234
235             $this->sp = 0;
236             return 1;
237         }
238
239         if ($this->Fresh) {
240             $this->Fresh = 0;
241             do {
242                 $this->FirstCode = $this->GetCode($data, $bInit);
243                 $this->OldCode   = $this->FirstCode;
244             }
245             while ($this->FirstCode == $this->ClearCode);
246
247             return $this->FirstCode;
248         }
249
250         if ($this->sp > 0) {
251             $this->sp--;
252             return $this->Stack[$this->sp];
253         }
254
255         while (($Code = $this->GetCode($data, $bInit)) >= 0) {
256             if ($Code == $this->ClearCode) {
257                 for ($i = 0; $i < $this->ClearCode; $i++) {
258                     $this->Next[$i] = 0;
259                     $this->Vals[$i] = $i;
260                 }
261
262                 for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
263                     $this->Next[$i] = 0;
264                     $this->Vals[$i] = 0;
265                 }
266
267                 $this->CodeSize    = $this->SetCodeSize + 1;
268                 $this->MaxCodeSize = $this->ClearCode << 1;
269                 $this->MaxCode     = $this->ClearCode + 2;
270                 $this->sp          = 0;
271                 $this->FirstCode   = $this->GetCode($data, $bInit);
272                 $this->OldCode     = $this->FirstCode;
273
274                 return $this->FirstCode;
275             }
276
277             if ($Code == $this->EndCode) {
278                 return -2;
279             }
280
281             $InCode = $Code;
282             if ($Code >= $this->MaxCode) {
283                 $this->Stack[$this->sp] = $this->FirstCode;
284                 $this->sp++;
285                 $Code = $this->OldCode;
286             }
287
288             while ($Code >= $this->ClearCode) {
289                 $this->Stack[$this->sp] = $this->Vals[$Code];
290                 $this->sp++;
291
292                 if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
293                     return -1;
294
295                 $Code = $this->Next[$Code];
296             }
297
298             $this->FirstCode = $this->Vals[$Code];
299             $this->Stack[$this->sp] = $this->FirstCode;
300             $this->sp++;
301
302             if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) {
303                 $this->Next[$Code] = $this->OldCode;
304                 $this->Vals[$Code] = $this->FirstCode;
305                 $this->MaxCode++;
306
307                 if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) {
308                     $this->MaxCodeSize *= 2;
309                     $this->CodeSize++;
310                 }
311             }
312
313             $this->OldCode = $InCode;
314             if ($this->sp > 0) {
315                 $this->sp--;
316                 return $this->Stack[$this->sp];
317             }
318         }
319
320         return $Code;
321     }
322
323     ///////////////////////////////////////////////////////////////////////////
324
325     function GetCode(&$data, $bInit)
326     {
327         if ($bInit) {
328             $this->CurBit   = 0;
329             $this->LastBit  = 0;
330             $this->Done     = 0;
331             $this->LastByte = 2;
332             return 1;
333         }
334
335         if (($this->CurBit + $this->CodeSize) >= $this->LastBit) {
336             if ($this->Done) {
337                 if ($this->CurBit >= $this->LastBit) {
338                     // Ran off the end of my bits
339                     return 0;
340                 }
341                 return -1;
342             }
343
344             $this->Buf[0] = $this->Buf[$this->LastByte - 2];
345             $this->Buf[1] = $this->Buf[$this->LastByte - 1];
346
347             $Count = ord($data{0});
348             $data  = substr($data, 1);
349
350             if ($Count) {
351                 for ($i = 0; $i < $Count; $i++) {
352                     $this->Buf[2 + $i] = ord($data{$i});
353                 }
354                 $data = substr($data, $Count);
355             } else {
356                 $this->Done = 1;
357             }
358
359             $this->LastByte = 2 + $Count;
360             $this->CurBit   = ($this->CurBit - $this->LastBit) + 16;
361             $this->LastBit  = (2 + $Count) << 3;
362         }
363
364         $iRet = 0;
365         for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) {
366             $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
367         }
368
369         $this->CurBit += $this->CodeSize;
370         return $iRet;
371     }
372 }
373
374 ///////////////////////////////////////////////////////////////////////////////////////////////////
375
376 class CGIFCOLORTABLE
377 {
378     var $m_nColors;
379     var $m_arColors;
380
381     ///////////////////////////////////////////////////////////////////////////
382
383     // CONSTRUCTOR
384     function CGIFCOLORTABLE()
385     {
386         unSet($this->m_nColors);
387         unSet($this->m_arColors);
388     }
389
390     ///////////////////////////////////////////////////////////////////////////
391
392     function load($lpData, $num)
393     {
394         $this->m_nColors  = 0;
395         $this->m_arColors = array();
396
397         for ($i = 0; $i < $num; $i++) {
398             $rgb = substr($lpData, $i * 3, 3);
399             if (strlen($rgb) < 3) {
400                 return false;
401             }
402
403             $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0});
404             $this->m_nColors++;
405         }
406
407         return true;
408     }
409
410     ///////////////////////////////////////////////////////////////////////////
411
412     function toString()
413     {
414         $ret = '';
415
416         for ($i = 0; $i < $this->m_nColors; $i++) {
417             $ret .=
418                 chr(($this->m_arColors[$i] & 0x000000FF))       . // R
419                 chr(($this->m_arColors[$i] & 0x0000FF00) >>  8) . // G
420                 chr(($this->m_arColors[$i] & 0x00FF0000) >> 16);  // B
421         }
422
423         return $ret;
424     }
425
426     ///////////////////////////////////////////////////////////////////////////
427
428     function toRGBQuad()
429     {
430         $ret = '';
431
432         for ($i = 0; $i < $this->m_nColors; $i++) {
433             $ret .=
434                 chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B
435                 chr(($this->m_arColors[$i] & 0x0000FF00) >>  8) . // G
436                 chr(($this->m_arColors[$i] & 0x000000FF))       . // R
437                 "\x00";
438         }
439
440         return $ret;
441     }
442
443     ///////////////////////////////////////////////////////////////////////////
444
445     function colorIndex($rgb)
446     {
447         $rgb  = intval($rgb) & 0xFFFFFF;
448         $r1   = ($rgb & 0x0000FF);
449         $g1   = ($rgb & 0x00FF00) >>  8;
450         $b1   = ($rgb & 0xFF0000) >> 16;
451         $idx  = -1;
452
453         for ($i = 0; $i < $this->m_nColors; $i++) {
454             $r2 = ($this->m_arColors[$i] & 0x000000FF);
455             $g2 = ($this->m_arColors[$i] & 0x0000FF00) >>  8;
456             $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
457             $d  = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
458
459             if (($idx == -1) || ($d < $dif)) {
460                 $idx = $i;
461                 $dif = $d;
462             }
463         }
464
465         return $idx;
466     }
467 }
468
469 ///////////////////////////////////////////////////////////////////////////////////////////////////
470
471 class CGIFFILEHEADER
472 {
473     var $m_lpVer;
474     var $m_nWidth;
475     var $m_nHeight;
476     var $m_bGlobalClr;
477     var $m_nColorRes;
478     var $m_bSorted;
479     var $m_nTableSize