3 ///////////////////////////////////////////////////////////////////////////////////////////////////
4 // 2009-12-22 Adapted for mPDF 4.2
5 ///////////////////////////////////////////////////////////////////////////////////////////////////
6 // GIF Util - (C) 2003 Yamasoft (S/C)
7 // http://www.yamasoft.com
9 // This file can be freely copied, distributed, modified, updated by anyone under the only
10 // condition to leave the original address (Yamasoft, http://www.yamasoft.com) and this header.
11 ///////////////////////////////////////////////////////////////////////////////////////////////////
12 ///////////////////////////////////////////////////////////////////////////////////////////////////
13 // 2009-12-22 Adapted INB
14 // Functions calling functionname($x, $len = 0) were not working on PHP5.1.5 as pass by reference
15 // All edited to $len = 0; then call function.
16 ///////////////////////////////////////////////////////////////////////////////////////////////////
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
24 var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
26 var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
28 public function __construct()
30 $this->MAX_LZW_BITS
= 12;
36 $this->Next
= range(0, (1 << $this->MAX_LZW_BITS
) - 1);
37 $this->Vals
= range(0, (1 << $this->MAX_LZW_BITS
) - 1);
38 $this->Stack
= range(0, (1 << ($this->MAX_LZW_BITS +
1)) - 1);
39 $this->Buf
= range(0, 279);
42 function deCompress($data, &$datLen)
44 $stLen = strlen($data);
47 $dp = 0; // data pointer
49 $this->LZWCommandInit($data, $dp);
51 while (($iIndex = $this->LZWCommand($data, $dp)) >= 0) {
64 function LZWCommandInit(&$data, &$dp)
66 $this->SetCodeSize
= ord($data[0]);
69 $this->CodeSize
= $this->SetCodeSize +
1;
70 $this->ClearCode
= 1 << $this->SetCodeSize
;
71 $this->EndCode
= $this->ClearCode +
1;
72 $this->MaxCode
= $this->ClearCode +
2;
73 $this->MaxCodeSize
= $this->ClearCode
<< 1;
75 $this->GetCodeInit($data, $dp);
78 for ($i = 0; $i < $this->ClearCode
; $i++
) {
83 for (; $i < (1 << $this->MAX_LZW_BITS
); $i++
) {
92 function LZWCommand(&$data, &$dp)
97 $this->FirstCode
= $this->GetCode($data, $dp);
98 $this->OldCode
= $this->FirstCode
;
99 } while ($this->FirstCode
== $this->ClearCode
);
101 return $this->FirstCode
;
106 return $this->Stack
[$this->sp
];
109 while (($Code = $this->GetCode($data, $dp)) >= 0) {
110 if ($Code == $this->ClearCode
) {
111 for ($i = 0; $i < $this->ClearCode
; $i++
) {
113 $this->Vals
[$i] = $i;
116 for (; $i < (1 << $this->MAX_LZW_BITS
); $i++
) {
121 $this->CodeSize
= $this->SetCodeSize +
1;
122 $this->MaxCodeSize
= $this->ClearCode
<< 1;
123 $this->MaxCode
= $this->ClearCode +
2;
125 $this->FirstCode
= $this->GetCode($data, $dp);
126 $this->OldCode
= $this->FirstCode
;
128 return $this->FirstCode
;
131 if ($Code == $this->EndCode
) {
136 if ($Code >= $this->MaxCode
) {
137 $this->Stack
[$this->sp++
] = $this->FirstCode
;
138 $Code = $this->OldCode
;
141 while ($Code >= $this->ClearCode
) {
142 $this->Stack
[$this->sp++
] = $this->Vals
[$Code];
144 if ($Code == $this->Next
[$Code]) // Circular table entry, big GIF Error!
147 $Code = $this->Next
[$Code];
150 $this->FirstCode
= $this->Vals
[$Code];
151 $this->Stack
[$this->sp++
] = $this->FirstCode
;
153 if (($Code = $this->MaxCode
) < (1 << $this->MAX_LZW_BITS
)) {
154 $this->Next
[$Code] = $this->OldCode
;
155 $this->Vals
[$Code] = $this->FirstCode
;
158 if (($this->MaxCode
>= $this->MaxCodeSize
) && ($this->MaxCodeSize
< (1 << $this->MAX_LZW_BITS
))) {
159 $this->MaxCodeSize
*= 2;
164 $this->OldCode
= $InCode;
167 return $this->Stack
[$this->sp
];
174 function GetCodeInit(&$data, &$dp)
183 function GetCode(&$data, &$dp)
185 if (($this->CurBit +
$this->CodeSize
) >= $this->LastBit
) {
187 if ($this->CurBit
>= $this->LastBit
) {
188 // Ran off the end of my bits
194 $this->Buf
[0] = $this->Buf
[$this->LastByte
- 2];
195 $this->Buf
[1] = $this->Buf
[$this->LastByte
- 1];
197 $Count = ord($data[$dp]);
201 for ($i = 0; $i < $Count; $i++
) {
202 $this->Buf
[2 +
$i] = ord($data[$dp +
$i]);
209 $this->LastByte
= 2 +
$Count;
210 $this->CurBit
= ($this->CurBit
- $this->LastBit
) +
16;
211 $this->LastBit
= (2 +
$Count) << 3;
215 for ($i = $this->CurBit
, $j = 0; $j < $this->CodeSize
; $i++
, $j++
) {
216 $iRet |
= (($this->Buf
[intval($i / 8)] & (1 << ($i %
8))) != 0) << $j;
219 $this->CurBit +
= $this->CodeSize
;
232 public function __construct()
234 unSet($this->m_nColors
);
235 unSet($this->m_arColors
);
238 function load($lpData, $num)
240 $this->m_nColors
= 0;
241 $this->m_arColors
= array();
243 for ($i = 0; $i < $num; $i++
) {
244 $rgb = substr($lpData, $i * 3, 3);
245 if (strlen($rgb) < 3) {
249 $this->m_arColors
[] = (ord($rgb[2]) << 16) +
(ord($rgb[1]) << 8) +
ord($rgb[0]);
260 for ($i = 0; $i < $this->m_nColors
; $i++
) {
262 chr(($this->m_arColors
[$i] & 0x000000FF)) . // R
263 chr(($this->m_arColors
[$i] & 0x0000FF00) >> 8) . // G
264 chr(($this->m_arColors
[$i] & 0x00FF0000) >> 16); // B
270 function colorIndex($rgb)
272 $rgb = intval($rgb) & 0xFFFFFF;
273 $r1 = ($rgb & 0x0000FF);
274 $g1 = ($rgb & 0x00FF00) >> 8;
275 $b1 = ($rgb & 0xFF0000) >> 16;
278 for ($i = 0; $i < $this->m_nColors
; $i++
) {
279 $r2 = ($this->m_arColors
[$i] & 0x000000FF);
280 $g2 = ($this->m_arColors
[$i] & 0x0000FF00) >> 8;
281 $b2 = ($this->m_arColors
[$i] & 0x00FF0000) >> 16;
282 $d = abs($r2 - $r1) +
abs($g2 - $g1) +
abs($b2 - $b1);
284 if (($idx == -1) ||
($d < $dif)) {
318 public function __construct()
320 unSet($this->m_lpVer
);
321 unSet($this->m_nWidth
);
322 unSet($this->m_nHeight
);
323 unSet($this->m_bGlobalClr
);
324 unSet($this->m_nColorRes
);
325 unSet($this->m_bSorted
);
326 unSet($this->m_nTableSize
);
327 unSet($this->m_nBgColor
);
328 unSet($this->m_nPixelRatio
);
329 unSet($this->m_colorTable
);
332 function load($lpData, &$hdrLen)
336 $this->m_lpVer
= substr($lpData, 0, 6);
337 if (($this->m_lpVer
<> "GIF87a") && ($this->m_lpVer
<> "GIF89a")) {
341 $this->m_nWidth
= $this->w2i(substr($lpData, 6, 2));
342 $this->m_nHeight
= $this->w2i(substr($lpData, 8, 2));
343 if (!$this->m_nWidth ||
!$this->m_nHeight
) {
347 $b = ord(substr($lpData, 10, 1));
348 $this->m_bGlobalClr
= ($b & 0x80) ?
true : false;
349 $this->m_nColorRes
= ($b & 0x70) >> 4;
350 $this->m_bSorted
= ($b & 0x08) ?
true : false;
351 $this->m_nTableSize
= 2 << ($b & 0x07);
352 $this->m_nBgColor
= ord(substr($lpData, 11, 1));
353 $this->m_nPixelRatio
= ord(substr($lpData, 12, 1));
356 if ($this->m_bGlobalClr
) {
357 $this->m_colorTable
= new CGIFCOLORTABLE();
358 if (!$this->m_colorTable
->load(substr($lpData, $hdrLen), $this->m_nTableSize
)) {
361 $hdrLen +
= 3 * $this->m_nTableSize
;
369 return ord(substr($str, 0, 1)) +
(ord(substr($str, 1, 1)) << 8);
374 class CGIFIMAGEHEADER
395 public function __construct()
397 unSet($this->m_nLeft
);
398 unSet($this->m_nTop
);
399 unSet($this->m_nWidth
);
400 unSet($this->m_nHeight
);
401 unSet($this->m_bLocalClr
);
402 unSet($this->m_bInterlace
);
403 unSet($this->m_bSorted
);
404 unSet($this->m_nTableSize
);
405 unSet($this->m_colorTable
);
408 function load($lpData, &$hdrLen)
412 $this->m_nLeft
= $this->w2i(substr($lpData, 0, 2));
413 $this->m_nTop
= $this->w2i(substr($lpData, 2, 2));
414 $this->m_nWidth
= $this->w2i(substr($lpData, 4, 2));
415 $this->m_nHeight
= $this->w2i(substr($lpData, 6, 2));
417 if (!$this->m_nWidth ||
!$this->m_nHeight
) {
421 $b = ord($lpData{8});
422 $this->m_bLocalClr
= ($b & 0x80) ?
true : false;
423 $this->m_bInterlace
= ($b & 0x40) ?
true : false;
424 $this->m_bSorted
= ($b & 0x20) ?
true : false;
425 $this->m_nTableSize
= 2 << ($b & 0x07);
428 if ($this->m_bLocalClr
) {
429 $this->m_colorTable
= new CGIFCOLORTABLE();
430 if (!$this->m_colorTable
->load(substr($lpData, $hdrLen), $this->m_nTableSize
)) {
433 $hdrLen +
= 3 * $this->m_nTableSize
;
441 return ord(substr($str, 0, 1)) +
(ord(substr($str, 1, 1)) << 8);
467 public function __construct()
469 unSet($this->m_disp
);
470 unSet($this->m_bUser
);
471 unSet($this->m_bTrans
);
472 unSet($this->m_nDelay
);
473 unSet($this->m_nTrans
);
474 unSet($this->m_lpComm
);
475 unSet($this->m_data
);
476 $this->m_gih
= new CGIFIMAGEHEADER();
477 $this->m_lzw
= new CGIFLZW();
480 function load($data, &$datLen)
486 $data = substr($data, 1);
490 case 0x21: // Extension
492 if (!$this->skipExt($data, $len)) {
499 // LOAD HEADER & COLOR TABLE
501 if (!$this->m_gih
->load($data, $len)) {
504 $data = substr($data, $len);
510 if (!($this->m_data
= $this->m_lzw
->deCompress($data, $len))) {
514 $data = substr($data, $len);
517 if ($this->m_gih
->m_bInterlace
) {
518 $this->deInterlace();
531 function skipExt(&$data, &$extLen)
536 $data = substr($data, 1);
540 case 0xF9: // Graphic Control
542 $this->m_disp
= ($b & 0x1C) >> 2;
543 $this->m_bUser
= ($b & 0x02) ?
true : false;
544 $this->m_bTrans
= ($b & 0x01) ?
true : false;
545 $this->m_nDelay
= $this->w2i(substr($data, 2, 2));
546 $this->m_nTrans
= ord($data[4]);
549 case 0xFE: // Comment
550 $this->m_lpComm
= substr($data, 1, ord($data[0]));
553 case 0x01: // Plain text
556 case 0xFF: // Application
560 // SKIP DEFAULT AS DEFS MAY CHANGE
562 $data = substr($data, 1);
565 $data = substr($data, $b);
568 $data = substr($data, 1);
576 return ord(substr($str, 0, 1)) +
(ord(substr($str, 1, 1)) << 8);
579 function deInterlace()
581 $data = $this->m_data
;
583 for ($i = 0; $i < 4; $i++
) {
606 for (; $y < $this->m_gih
->m_nHeight
; $y +
= $s) {
607 $lne = substr($this->m_data
, 0, $this->m_gih
->m_nWidth
);
608 $this->m_data
= substr($this->m_data
, $this->m_gih
->m_nWidth
);
610 $data = substr($data, 0, $y * $this->m_gih
->m_nWidth
) .
612 substr($data, ($y +
1) * $this->m_gih
->m_nWidth
);
616 $this->m_data
= $data;
632 public function __construct()
634 $this->m_gfh
= new CGIFFILEHEADER();
635 $this->m_img
= new CGIFIMAGE();
636 $this->m_lpData
= "";
637 $this->m_bLoaded
= false;
642 $this->m_lpData
= '';
643 unSet($this->m_img
->m_data
);
644 unSet($this->m_img
->m_lzw
->Next
);
645 unSet($this->m_img
->m_lzw
->Vals
);
646 unSet($this->m_img
->m_lzw
->Stack
);
647 unSet($this->m_img
->m_lzw
->Buf
);
650 function loadFile(&$data, $iIndex)
655 $this->m_lpData
= $data;
659 if (!$this->m_gfh
->load($this->m_lpData
, $len)) {
663 $this->m_lpData
= substr($this->m_lpData
, $len);
667 if (!$this->m_img
->load($this->m_lpData
, $imgLen)) {
670 $this->m_lpData
= substr($this->m_lpData
, $imgLen);
671 } while ($iIndex-- > 0);
673 $this->m_bLoaded
= true;