source-class-TCPDF_FILTERS

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
Overview

Classes

Interfaces

Exceptions

Functions

  1: <?php
  2: //============================================================+
  3: // File name   : tcpdf_filters.php
  4: // Version     : 1.0.001
  5: // Begin       : 2011-05-23
  6: // Last Update : 2014-04-25
  7: // Author      : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
  8: // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
  9: // -------------------------------------------------------------------
 10: // Copyright (C) 2011-2013 Nicola Asuni - Tecnick.com LTD
 11: //
 12: // This file is part of TCPDF software library.
 13: //
 14: // TCPDF is free software: you can redistribute it and/or modify it
 15: // under the terms of the GNU Lesser General Public License as
 16: // published by the Free Software Foundation, either version 3 of the
 17: // License, or (at your option) any later version.
 18: //
 19: // TCPDF is distributed in the hope that it will be useful, but
 20: // WITHOUT ANY WARRANTY; without even the implied warranty of
 21: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 22: // See the GNU Lesser General Public License for more details.
 23: //
 24: // You should have received a copy of the License
 25: // along with TCPDF. If not, see
 26: // <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
 27: //
 28: // See LICENSE.TXT file for more information.
 29: // -------------------------------------------------------------------
 30: //
 31: // Description : This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).
 32: //
 33: //============================================================+
 34: 
 35: /**
 36:  * @file
 37:  * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br>
 38:  * @package com.tecnick.tcpdf
 39:  * @author Nicola Asuni
 40:  * @version 1.0.001
 41:  */
 42: 
 43: /**
 44:  * @class TCPDF_FILTERS
 45:  * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br>
 46:  * @package com.tecnick.tcpdf
 47:  * @brief This is a PHP class for decoding common PDF filters.
 48:  * @version 1.0.001
 49:  * @author Nicola Asuni - info@tecnick.com
 50:  */
 51: class TCPDF_FILTERS {
 52: 
 53:     /**
 54:      * Define a list of available filter decoders.
 55:      * @private static
 56:      */
 57:     private static $available_filters = array('ASCIIHexDecode', 'ASCII85Decode', 'LZWDecode', 'FlateDecode', 'RunLengthDecode');
 58: 
 59: // -----------------------------------------------------------------------------
 60: 
 61:     /**
 62:      * Get a list of available decoding filters.
 63:      * @return (array) Array of available filter decoders.
 64:      * @since 1.0.000 (2011-05-23)
 65:      * @public static
 66:      */
 67:     public static function getAvailableFilters() {
 68:         return self::$available_filters;
 69:     }
 70: 
 71:     /**
 72:      * Decode data using the specified filter type.
 73:      * @param $filter (string) Filter name.
 74:      * @param $data (string) Data to decode.
 75:      * @return Decoded data string.
 76:      * @since 1.0.000 (2011-05-23)
 77:      * @public static
 78:      */
 79:     public static function decodeFilter($filter, $data) {
 80:         switch ($filter) {
 81:             case 'ASCIIHexDecode': {
 82:                 return self::decodeFilterASCIIHexDecode($data);
 83:                 break;
 84:             }
 85:             case 'ASCII85Decode': {
 86:                 return self::decodeFilterASCII85Decode($data);
 87:                 break;
 88:             }
 89:             case 'LZWDecode': {
 90:                 return self::decodeFilterLZWDecode($data);
 91:                 break;
 92:             }
 93:             case 'FlateDecode': {
 94:                 return self::decodeFilterFlateDecode($data);
 95:                 break;
 96:             }
 97:             case 'RunLengthDecode': {
 98:                 return self::decodeFilterRunLengthDecode($data);
 99:                 break;
100:             }
101:             case 'CCITTFaxDecode': {
102:                 return self::decodeFilterCCITTFaxDecode($data);
103:                 break;
104:             }
105:             case 'JBIG2Decode': {
106:                 return self::decodeFilterJBIG2Decode($data);
107:                 break;
108:             }
109:             case 'DCTDecode': {
110:                 return self::decodeFilterDCTDecode($data);
111:                 break;
112:             }
113:             case 'JPXDecode': {
114:                 return self::decodeFilterJPXDecode($data);
115:                 break;
116:             }
117:             case 'Crypt': {
118:                 return self::decodeFilterCrypt($data);
119:                 break;
120:             }
121:             default: {
122:                 return self::decodeFilterStandard($data);
123:                 break;
124:             }
125:         }
126:     }
127: 
128:     // --- FILTERS (PDF 32000-2008 - 7.4 Filters) ------------------------------
129: 
130:     /**
131:      * Standard
132:      * Default decoding filter (leaves data unchanged).
133:      * @param $data (string) Data to decode.
134:      * @return Decoded data string.
135:      * @since 1.0.000 (2011-05-23)
136:      * @public static
137:      */
138:     public static function decodeFilterStandard($data) {
139:         return $data;
140:     }
141: 
142:     /**
143:      * ASCIIHexDecode
144:      * Decodes data encoded in an ASCII hexadecimal representation, reproducing the original binary data.
145:      * @param $data (string) Data to decode.
146:      * @return Decoded data string.
147:      * @since 1.0.000 (2011-05-23)
148:      * @public static
149:      */
150:     public static function decodeFilterASCIIHexDecode($data) {
151:         // initialize string to return
152:         $decoded = '';
153:         // all white-space characters shall be ignored
154:         $data = preg_replace('/[\s]/', '', $data);
155:         // check for EOD character: GREATER-THAN SIGN (3Eh)
156:         $eod = strpos($data, '>');
157:         if ($eod !== false) {
158:             // remove EOD and extra data (if any)
159:             $data = substr($data, 0, $eod);
160:             $eod = true;
161:         }
162:         // get data length
163:         $data_length = strlen($data);
164:         if (($data_length % 2) != 0) {
165:             // odd number of hexadecimal digits
166:             if ($eod) {
167:                 // EOD shall behave as if a 0 (zero) followed the last digit
168:                 $data = substr($data, 0, -1).'0'.substr($data, -1);
169:             } else {
170:                 self::Error('decodeFilterASCIIHexDecode: invalid code');
171:             }
172:         }
173:         // check for invalid characters
174:         if (preg_match('/[^a-fA-F\d]/', $data) > 0) {
175:             self::Error('decodeFilterASCIIHexDecode: invalid code');
176:         }
177:         // get one byte of binary data for each pair of ASCII hexadecimal digits
178:         $decoded = pack('H*', $data);
179:         return $decoded;
180:     }
181: 
182:     /**
183:      * ASCII85Decode
184:      * Decodes data encoded in an ASCII base-85 representation, reproducing the original binary data.
185:      * @param $data (string) Data to decode.
186:      * @return Decoded data string.
187:      * @since 1.0.000 (2011-05-23)
188:      * @public static
189:      */
190:     public static function decodeFilterASCII85Decode($data) {
191:         // initialize string to return
192:         $decoded = '';
193:         // all white-space characters shall be ignored
194:         $data = preg_replace('/[\s]/', '', $data);
195:         // remove start sequence 2-character sequence <~ (3Ch)(7Eh)
196:         if (strpos($data, '<~') !== false) {
197:             // remove EOD and extra data (if any)
198:             $data = substr($data, 2);
199:         }
200:         // check for EOD: 2-character sequence ~> (7Eh)(3Eh)
201:         $eod = strpos($data, '~>');
202:         if ($eod !== false) {
203:             // remove EOD and extra data (if any)
204:             $data = substr($data, 0, $eod);
205:         }
206:         // data length
207:         $data_length = strlen($data);
208:         // check for invalid characters
209:         if (preg_match('/[^\x21-\x75,\x74]/', $data) > 0) {
210:             self::Error('decodeFilterASCII85Decode: invalid code');
211:         }
212:         // z sequence
213:         $zseq = chr(0).chr(0).chr(0).chr(0);
214:         // position inside a group of 4 bytes (0-3)
215:         $group_pos = 0;
216:         $tuple = 0;
217:         $pow85 = array((85*85*85*85), (85*85*85), (85*85), 85, 1);
218:         $last_pos = ($data_length - 1);
219:         // for each byte
220:         for ($i = 0; $i < $data_length; ++$i) {
221:             // get char value
222:             $char = ord($data[$i]);
223:             if ($char == 122) { // 'z'
224:                 if ($group_pos == 0) {
225:                     $decoded .= $zseq;
226:                 } else {
227:                     self::Error('decodeFilterASCII85Decode: invalid code');
228:                 }
229:             } else {
230:                 // the value represented by a group of 5 characters should never be greater than 2^32 - 1
231:                 $tuple += (($char - 33) * $pow85[$group_pos]);
232:                 if ($group_pos == 4) {
233:                     $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8).chr($tuple);
234:                     $tuple = 0;
235:                     $group_pos = 0;
236:                 } else {
237:                     ++$group_pos;
238:                 }
239:             }
240:         }
241:         if ($group_pos > 1) {
242:             $tuple += $pow85[($group_pos - 1)];
243:         }
244:         // last tuple (if any)
245:         switch ($group_pos) {
246:             case 4: {
247:                 $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8);
248:                 break;
249:             }
250:             case 3: {
251:                 $decoded .= chr($tuple >> 24).chr($tuple >> 16);
252:                 break;
253:             }
254:             case 2: {
255:                 $decoded .= chr($tuple >> 24);
256:                 break;
257:             }
258:             case 1: {
259:                 self::Error('decodeFilterASCII85Decode: invalid code');
260:                 break;
261:             }
262:         }
263:         return $decoded;
264:     }
265: 
266:     /**
267:      * LZWDecode
268:      * Decompresses data encoded using the LZW (Lempel-Ziv-Welch) adaptive compression method, reproducing the original text or binary data.
269:      * @param $data (string) Data to decode.
270:      * @return Decoded data string.
271:      * @since 1.0.000 (2011-05-23)
272:      * @public static
273:      */
274:     public static function decodeFilterLZWDecode($data) {
275:         // initialize string to return
276:         $decoded = '';
277:         // data length
278:         $data_length = strlen($data);
279:         // convert string to binary string
280:         $bitstring = '';
281:         for ($i = 0; $i < $data_length; ++$i) {
282:             $bitstring .= sprintf('%08b', ord($data{$i}));
283:         }
284:         // get the number of bits
285:         $data_length = strlen($bitstring);
286:         // initialize code length in bits
287:         $bitlen = 9;
288:         // initialize dictionary index
289:         $dix = 258;
290:         // initialize the dictionary (with the first 256 entries).
291:         $dictionary = array();
292:         for ($i = 0; $i < 256; ++$i) {
293:             $dictionary[$i] = chr($i);
294:         }
295:         // previous val
296:         $prev_index = 0;
297:         // while we encounter EOD marker (257), read code_length bits
298:         while (($data_length > 0) AND (($index = bindec(substr($bitstring, 0, $bitlen))) != 257)) {
299:             // remove read bits from string
300:             $bitstring = substr($bitstring, $bitlen);
301:             // update number of bits
302:             $data_length -= $bitlen;
303:             if ($index == 256) { // clear-table marker
304:                 // reset code length in bits
305:                 $bitlen = 9;
306:                 // reset dictionary index
307:                 $dix = 258;
308:                 $prev_index = 256;
309:                 // reset the dictionary (with the first 256 entries).
310:                 $dictionary = array();
311:                 for ($i = 0; $i < 256; ++$i) {
312:                     $dictionary[$i] = chr($i);
313:                 }
314:             } elseif ($prev_index == 256) {
315:                 // first entry
316:                 $decoded .= $dictionary[$index];
317:                 $prev_index = $index;
318:             } else {
319:                 // check if index exist in the dictionary
320:                 if ($index < $dix) {
321:                     // index exist on dictionary
322:                     $decoded .= $dictionary[$index];
323:                     $dic_val = $dictionary[$prev_index].$dictionary[$index][0];
324:                     // store current index
325:                     $prev_index = $index;
326:                 } else {
327:                     // index do not exist on dictionary
328:                     $dic_val = $dictionary[$prev_index].$dictionary[$prev_index][0];
329:                     $decoded .= $dic_val;
330:                 }
331:                 // update dictionary
332:                 $dictionary[$dix] = $dic_val;
333:                 ++$dix;
334:                 // change bit length by case
335:                 if ($dix == 2047) {
336:                     $bitlen = 12;
337:                 } elseif ($dix == 1023) {
338:                     $bitlen = 11;
339:                 } elseif ($dix == 511) {
340:                     $bitlen = 10;
341:                 }
342:             }
343:         }
344:         return $decoded;
345:     }
346: 
347:     /**
348:      * FlateDecode
349:      * Decompresses data encoded using the zlib/deflate compression method, reproducing the original text or binary data.
350:      * @param $data (string) Data to decode.
351:      * @return Decoded data string.
352:      * @since 1.0.000 (2011-05-23)
353:      * @public static
354:      */
355:     public static function decodeFilterFlateDecode($data) {
356:         // initialize string to return
357:         $decoded = @gzuncompress($data);
358:         if ($decoded === false) {
359:             self::Error('decodeFilterFlateDecode: invalid code');
360:         }
361:         return $decoded;
362:     }
363: 
364:     /**
365:      * RunLengthDecode
366:      * Decompresses data encoded using a byte-oriented run-length encoding algorithm.
367:      * @param $data (string) Data to decode.
368:      * @since 1.0.000 (2011-05-23)
369:      * @public static
370:      */
371:     public static function decodeFilterRunLengthDecode($data) {
372:         // initialize string to return
373:         $decoded = '';
374:         // data length
375:         $data_length = strlen($data);
376:         $i = 0;
377:         while($i < $data_length) {
378:             // get current byte value
379:             $byte = ord($data{$i});
380:             if ($byte == 128) {
381:                 // a length value of 128 denote EOD
382:                 break;
383:             } elseif ($byte < 128) {
384:                 // if the length byte is in the range 0 to 127
385:                 // the following length + 1 (1 to 128) bytes shall be copied literally during decompression
386:                 $decoded .= substr($data, ($i + 1), ($byte + 1));
387:                 // move to next block
388:                 $i += ($byte + 2);
389:             } else {
390:                 // if length is in the range 129 to 255,
391:                 // the following single byte shall be copied 257 - length (2 to 128) times during decompression
392:                 $decoded .= str_repeat($data{($i + 1)}, (257 - $byte));
393:                 // move to next block
394:                 $i += 2;
395:             }
396:         }
397:         return $decoded;
398:     }
399: 
400:     /**
401:      * CCITTFaxDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
402:      * Decompresses data encoded using the CCITT facsimile standard, reproducing the original data (typically monochrome image data at 1 bit per pixel).
403:      * @param $data (string) Data to decode.
404:      * @return Decoded data string.
405:      * @since 1.0.000 (2011-05-23)
406:      * @public static
407:      */
408:     public static function decodeFilterCCITTFaxDecode($data) {
409:         self::Error('~decodeFilterCCITTFaxDecode: this method has not been yet implemented');
410:         //return $data;
411:     }
412: 
413:     /**
414:      * JBIG2Decode (NOT IMPLEMETED - RETURN AN EXCEPTION)
415:      * Decompresses data encoded using the JBIG2 standard, reproducing the original monochrome (1 bit per pixel) image data (or an approximation of that data).
416:      * @param $data (string) Data to decode.
417:      * @return Decoded data string.
418:      * @since 1.0.000 (2011-05-23)
419:      * @public static
420:      */
421:     public static function decodeFilterJBIG2Decode($data) {
422:         self::Error('~decodeFilterJBIG2Decode: this method has not been yet implemented');
423:         //return $data;
424:     }
425: 
426:     /**
427:      * DCTDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
428:      * Decompresses data encoded using a DCT (discrete cosine transform) technique based on the JPEG standard, reproducing image sample data that approximates the original data.
429:      * @param $data (string) Data to decode.
430:      * @return Decoded data string.
431:      * @since 1.0.000 (2011-05-23)
432:      * @public static
433:      */
434:     public static function decodeFilterDCTDecode($data) {
435:         self::Error('~decodeFilterDCTDecode: this method has not been yet implemented');
436:         //return $data;
437:     }
438: 
439:     /**
440:      * JPXDecode (NOT IMPLEMETED - RETURN AN EXCEPTION)
441:      * Decompresses data encoded using the wavelet-based JPEG2000 standard, reproducing the original image data.
442:      * @param $data (string) Data to decode.
443:      * @return Decoded data string.
444:      * @since 1.0.000 (2011-05-23)
445:      * @public static
446:      */
447:     public static function decodeFilterJPXDecode($data) {
448:         self::Error('~decodeFilterJPXDecode: this method has not been yet implemented');
449:         //return $data;
450:     }
451: 
452:     /**
453:      * Crypt (NOT IMPLEMETED - RETURN AN EXCEPTION)
454:      * Decrypts data encrypted by a security handler, reproducing the data as it was before encryption.
455:      * @param $data (string) Data to decode.
456:      * @return Decoded data string.
457:      * @since 1.0.000 (2011-05-23)
458:      * @public static
459:      */
460:     public static function decodeFilterCrypt($data) {
461:         self::Error('~decodeFilterCrypt: this method has not been yet implemented');
462:         //return $data;
463:     }
464: 
465:     // --- END FILTERS SECTION -------------------------------------------------
466: 
467:     /**
468:      * Throw an exception.
469:      * @param $msg (string) The error message
470:      * @since 1.0.000 (2011-05-23)
471:      * @public static
472:      */
473:     public static function Error($msg) {
474:         throw new Exception('TCPDF_PARSER ERROR: '.$msg);
475:     }
476: 
477: } // END OF TCPDF_FILTERS CLASS
478: 
479: //============================================================+
480: // END OF FILE
481: //============================================================+
482: 
 

© 2004-2018 – Nicola Asuni - Tecnick.com - All rights reserved.
about - disclaimer - privacy