[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 //============================================================+ 3 // File name : barcodes.php 4 // Begin : 2008-06-09 5 // Last Update : 2009-08-26 6 // Version : 1.0.009 7 // License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html) 8 // ---------------------------------------------------------------------------- 9 // Copyright (C) 2008-2009 Nicola Asuni - Tecnick.com S.r.l. 10 // 11 // This program is free software: you can redistribute it and/or modify 12 // it under the terms of the GNU Lesser General Public License as published by 13 // the Free Software Foundation, either version 2.1 of the License, or 14 // (at your option) any later version. 15 // 16 // This program is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU Lesser General Public License for more details. 20 // 21 // You should have received a copy of the GNU Lesser General Public License 22 // along with this program. If not, see <http://www.gnu.org/licenses/>. 23 // 24 // See LICENSE.TXT file for more information. 25 // ---------------------------------------------------------------------------- 26 // 27 // Description : PHP class to creates array representations for 28 // common 1D barcodes to be used with TCPDF. 29 // 30 // Author: Nicola Asuni 31 // 32 // (c) Copyright: 33 // Nicola Asuni 34 // Tecnick.com S.r.l. 35 // Via della Pace, 11 36 // 09044 Quartucciu (CA) 37 // ITALY 38 // www.tecnick.com 39 // info@tecnick.com 40 //============================================================+ 41 42 /** 43 * PHP class to creates array representations for common 1D barcodes to be used with TCPDF. 44 * @package com.tecnick.tcpdf 45 * @abstract Functions for generating string representation of common 1D barcodes. 46 * @author Nicola Asuni 47 * @copyright 2008-2009 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com 48 * @link http://www.tcpdf.org 49 * @license http://www.gnu.org/copyleft/lesser.html LGPL 50 * @version 1.0.008 51 */ 52 53 /** 54 * PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br> 55 * @name TCPDFBarcode 56 * @package com.tecnick.tcpdf 57 * @version 1.0.008 58 * @author Nicola Asuni 59 * @link http://www.tcpdf.org 60 * @license http://www.gnu.org/copyleft/lesser.html LGPL 61 */ 62 class TCPDFBarcode { 63 64 /** 65 * @var array representation of barcode. 66 * @access protected 67 */ 68 protected $barcode_array; 69 70 /** 71 * This is the class constructor. 72 * Return an array representations for common 1D barcodes:<ul> 73 * <li>$arrcode['code'] code to be printed on text label</li> 74 * <li>$arrcode['maxh'] max bar height</li> 75 * <li>$arrcode['maxw'] max bar width</li> 76 * <li>$arrcode['bcode'][$k] single bar or space in $k position</li> 77 * <li>$arrcode['bcode'][$k]['t'] bar type: true = bar, false = space.</li> 78 * <li>$arrcode['bcode'][$k]['w'] bar width in units.</li> 79 * <li>$arrcode['bcode'][$k]['h'] bar height in units.</li> 80 * <li>$arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)</li></ul> 81 * @param string $code code to print 82 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul> 83 */ 84 public function __construct($code, $type) { 85 $this->setBarcode($code, $type); 86 } 87 88 /** 89 * Return an array representations of barcode. 90 * @return array 91 */ 92 public function getBarcodeArray() { 93 return $this->barcode_array; 94 } 95 96 /** 97 * Set the barcode. 98 * @param string $code code to print 99 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul> 100 * @return array 101 */ 102 public function setBarcode($code, $type) { 103 switch (strtoupper($type)) { 104 case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. 105 $arrcode = $this->barcode_code39($code, false, false); 106 break; 107 } 108 case 'C39+': { // CODE 39 with checksum 109 $arrcode = $this->barcode_code39($code, false, true); 110 break; 111 } 112 case 'C39E': { // CODE 39 EXTENDED 113 $arrcode = $this->barcode_code39($code, true, false); 114 break; 115 } 116 case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM 117 $arrcode = $this->barcode_code39($code, true, true); 118 break; 119 } 120 case 'C93': { // CODE 93 - USS-93 121 $arrcode = $this->barcode_code93($code); 122 break; 123 } 124 case 'S25': { // Standard 2 of 5 125 $arrcode = $this->barcode_s25($code, false); 126 break; 127 } 128 case 'S25+': { // Standard 2 of 5 + CHECKSUM 129 $arrcode = $this->barcode_s25($code, true); 130 break; 131 } 132 case 'I25': { // Interleaved 2 of 5 133 $arrcode = $this->barcode_i25($code, false); 134 break; 135 } 136 case 'I25+': { // Interleaved 2 of 5 + CHECKSUM 137 $arrcode = $this->barcode_i25($code, true); 138 break; 139 } 140 case 'C128A': { // CODE 128 A 141 $arrcode = $this->barcode_c128($code, 'A'); 142 break; 143 } 144 case 'C128B': { // CODE 128 B 145 $arrcode = $this->barcode_c128($code, 'B'); 146 break; 147 } 148 case 'C128C': { // CODE 128 C 149 $arrcode = $this->barcode_c128($code, 'C'); 150 break; 151 } 152 case 'EAN2': { // 2-Digits UPC-Based Extention 153 $arrcode = $this->barcode_eanext($code, 2); 154 break; 155 } 156 case 'EAN5': { // 5-Digits UPC-Based Extention 157 $arrcode = $this->barcode_eanext($code, 5); 158 break; 159 } 160 case 'EAN8': { // EAN 8 161 $arrcode = $this->barcode_eanupc($code, 8); 162 break; 163 } 164 case 'EAN13': { // EAN 13 165 $arrcode = $this->barcode_eanupc($code, 13); 166 break; 167 } 168 case 'UPCA': { // UPC-A 169 $arrcode = $this->barcode_eanupc($code, 12); 170 break; 171 } 172 case 'UPCE': { // UPC-E 173 $arrcode = $this->barcode_eanupc($code, 6); 174 break; 175 } 176 case 'MSI': { // MSI (Variation of Plessey code) 177 $arrcode = $this->barcode_msi($code, false); 178 break; 179 } 180 case 'MSI+': { // MSI + CHECKSUM (modulo 11) 181 $arrcode = $this->barcode_msi($code, true); 182 break; 183 } 184 case 'POSTNET': { // POSTNET 185 $arrcode = $this->barcode_postnet($code, false); 186 break; 187 } 188 case 'PLANET': { // PLANET 189 $arrcode = $this->barcode_postnet($code, true); 190 break; 191 } 192 case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) 193 $arrcode = $this->barcode_rms4cc($code, false); 194 break; 195 } 196 case 'KIX': { // KIX (Klant index - Customer index) 197 $arrcode = $this->barcode_rms4cc($code, true); 198 break; 199 } 200 case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 201 $arrcode = $this->barcode_imb($code); 202 break; 203 } 204 case 'CODABAR': { // CODABAR 205 $arrcode = $this->barcode_codabar($code); 206 break; 207 } 208 case 'CODE11': { // CODE 11 209 $arrcode = $this->barcode_code11($code); 210 break; 211 } 212 case 'PHARMA': { // PHARMACODE 213 $arrcode = $this->barcode_pharmacode($code); 214 break; 215 } 216 case 'PHARMA2T': { // PHARMACODE TWO-TRACKS 217 $arrcode = $this->barcode_pharmacode2t($code); 218 break; 219 } 220 default: { 221 $this->barcode_array = false; 222 $arrcode = false; 223 break; 224 } 225 } 226 $this->barcode_array = $arrcode; 227 } 228 229 /** 230 * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. 231 * General-purpose code in very wide use world-wide 232 * @param string $code code to represent. 233 * @param boolean $checksum if true add a checksum to the code 234 * @return array barcode representation. 235 * @access protected 236 */ 237 protected function barcode_code39($code, $extended=false, $checksum=false) { 238 $chr['0'] = '111221211'; 239 $chr['1'] = '211211112'; 240 $chr['2'] = '112211112'; 241 $chr['3'] = '212211111'; 242 $chr['4'] = '111221112'; 243 $chr['5'] = '211221111'; 244 $chr['6'] = '112221111'; 245 $chr['7'] = '111211212'; 246 $chr['8'] = '211211211'; 247 $chr['9'] = '112211211'; 248 $chr['A'] = '211112112'; 249 $chr['B'] = '112112112'; 250 $chr['C'] = '212112111'; 251 $chr['D'] = '111122112'; 252 $chr['E'] = '211122111'; 253 $chr['F'] = '112122111'; 254 $chr['G'] = '111112212'; 255 $chr['H'] = '211112211'; 256 $chr['I'] = '112112211'; 257 $chr['J'] = '111122211'; 258 $chr['K'] = '211111122'; 259 $chr['L'] = '112111122'; 260 $chr['M'] = '212111121'; 261 $chr['N'] = '111121122'; 262 $chr['O'] = '211121121'; 263 $chr['P'] = '112121121'; 264 $chr['Q'] = '111111222'; 265 $chr['R'] = '211111221'; 266 $chr['S'] = '112111221'; 267 $chr['T'] = '111121221'; 268 $chr['U'] = '221111112'; 269 $chr['V'] = '122111112'; 270 $chr['W'] = '222111111'; 271 $chr['X'] = '121121112'; 272 $chr['Y'] = '221121111'; 273 $chr['Z'] = '122121111'; 274 $chr['-'] = '121111212'; 275 $chr['.'] = '221111211'; 276 $chr[' '] = '122111211'; 277 $chr['$'] = '121212111'; 278 $chr['/'] = '121211121'; 279 $chr['+'] = '121112121'; 280 $chr['%'] = '111212121'; 281 $chr['*'] = '121121211'; 282 283 $code = strtoupper($code); 284 if ($extended) { 285 // extended mode 286 $code = $this->encode_code39_ext($code); 287 } 288 if ($code === false) { 289 return false; 290 } 291 if ($checksum) { 292 // checksum 293 $code .= $this->checksum_code39($code); 294 } 295 // add start and stop codes 296 $code = '*'.$code.'*'; 297 298 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 299 $k = 0; 300 $clen = strlen($code); 301 for ($i = 0; $i < $clen; ++$i) { 302 $char = $code{$i}; 303 if(!isset($chr[$char])) { 304 // invalid character 305 return false; 306 } 307 for ($j = 0; $j < 9; ++$j) { 308 if (($j % 2) == 0) { 309 $t = true; // bar 310 } else { 311 $t = false; // space 312 } 313 $w = $chr[$char]{$j}; 314 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 315 $bararray['maxw'] += $w; 316 ++$k; 317 } 318 $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0); 319 $bararray['maxw'] += 1; 320 ++$k; 321 } 322 return $bararray; 323 } 324 325 /** 326 * Encode a string to be used for CODE 39 Extended mode. 327 * @param string $code code to represent. 328 * @return encoded string. 329 * @access protected 330 */ 331 protected function encode_code39_ext($code) { 332 $encode = array( 333 chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C', 334 chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G', 335 chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K', 336 chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O', 337 chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S', 338 chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W', 339 chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A', 340 chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E', 341 chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C', 342 chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G', 343 chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K', 344 chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O', 345 chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', 346 chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', 347 chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F', 348 chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J', 349 chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', 350 chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', 351 chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', 352 chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', 353 chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', 354 chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', 355 chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K', 356 chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O', 357 chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C', 358 chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G', 359 chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K', 360 chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O', 361 chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S', 362 chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W', 363 chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P', 364 chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T'); 365 $code_ext = ''; 366 $clen = strlen($code); 367 for ($i = 0 ; $i < $clen; ++$i) { 368 if (ord($code{$i}) > 127) { 369 return false; 370 } 371 $code_ext .= $encode[$code{$i}]; 372 } 373 return $code_ext; 374 } 375 376 /** 377 * Calculate CODE 39 checksum (modulo 43). 378 * @param string $code code to represent. 379 * @return char checksum. 380 * @access protected 381 */ 382 protected function checksum_code39($code) { 383 $chars = array( 384 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 385 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 386 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 387 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%'); 388 $sum = 0; 389 $clen = strlen($code); 390 for ($i = 0 ; $i < $clen; ++$i) { 391 $k = array_keys($chars, $code{$i}); 392 $sum += $k[0]; 393 } 394 $j = ($sum % 43); 395 return $chars[$j]; 396 } 397 398 /** 399 * CODE 93 - USS-93 400 * Compact code similar to Code 39 401 * @param string $code code to represent. 402 * @param boolean $checksum if true add a checksum to the code 403 * @return array barcode representation. 404 * @access protected 405 */ 406 protected function barcode_code93($code) { 407 $chr['0'] = '131112'; 408 $chr['1'] = '111213'; 409 $chr['2'] = '111312'; 410 $chr['3'] = '111411'; 411 $chr['4'] = '121113'; 412 $chr['5'] = '121212'; 413 $chr['6'] = '121311'; 414 $chr['7'] = '111114'; 415 $chr['8'] = '131211'; 416 $chr['9'] = '141111'; 417 $chr['A'] = '211113'; 418 $chr['B'] = '211212'; 419 $chr['C'] = '211311'; 420 $chr['D'] = '221112'; 421 $chr['E'] = '221211'; 422 $chr['F'] = '231111'; 423 $chr['G'] = '112113'; 424 $chr['H'] = '112212'; 425 $chr['I'] = '112311'; 426 $chr['J'] = '122112'; 427 $chr['K'] = '132111'; 428 $chr['L'] = '111123'; 429 $chr['M'] = '111222'; 430 $chr['N'] = '111321'; 431 $chr['O'] = '121122'; 432 $chr['P'] = '131121'; 433 $chr['Q'] = '212112'; 434 $chr['R'] = '212211'; 435 $chr['S'] = '211122'; 436 $chr['T'] = '211221'; 437 $chr['U'] = '221121'; 438 $chr['V'] = '222111'; 439 $chr['W'] = '112122'; 440 $chr['X'] = '112221'; 441 $chr['Y'] = '122121'; 442 $chr['Z'] = '123111'; 443 $chr['-'] = '121131'; 444 $chr['.'] = '311112'; 445 $chr[' '] = '311211'; 446 $chr['$'] = '321111'; 447 $chr['/'] = '112131'; 448 $chr['+'] = '113121'; 449 $chr['%'] = '211131'; 450 $chr[128] = '121221'; // ($) 451 $chr[129] = '311121'; // (/) 452 $chr[130] = '122211'; // (+) 453 $chr[131] = '312111'; // (%) 454 $chr['*'] = '111141'; 455 $code = strtoupper($code); 456 $encode = array( 457 chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C', 458 chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G', 459 chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K', 460 chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O', 461 chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S', 462 chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W', 463 chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A', 464 chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E', 465 chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C', 466 chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G', 467 chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K', 468 chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O', 469 chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', 470 chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', 471 chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F', 472 chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J', 473 chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', 474 chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', 475 chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', 476 chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', 477 chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', 478 chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', 479 chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K', 480 chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O', 481 chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C', 482 chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G', 483 chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K', 484 chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O', 485 chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S', 486 chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W', 487 chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P', 488 chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T'); 489 $code_ext = ''; 490 $clen = strlen($code); 491 for ($i = 0 ; $i < $clen; ++$i) { 492 if (ord($code{$i}) > 127) { 493 return false; 494 } 495 $code_ext .= $encode[$code{$i}]; 496 } 497 // checksum 498 $code .= $this->checksum_code93($code); 499 // add start and stop codes 500 $code = '*'.$code.'*'; 501 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 502 $k = 0; 503 $clen = strlen($code); 504 for ($i = 0; $i < $clen; ++$i) { 505 $char = $code{$i}; 506 if(!isset($chr[$char])) { 507 // invalid character 508 return false; 509 } 510 for ($j = 0; $j < 6; ++$j) { 511 if (($j % 2) == 0) { 512 $t = true; // bar 513 } else { 514 $t = false; // space 515 } 516 $w = $chr[$char]{$j}; 517 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 518 $bararray['maxw'] += $w; 519 ++$k; 520 } 521 } 522 $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0); 523 $bararray['maxw'] += 1; 524 ++$k; 525 return $bararray; 526 } 527 528 /** 529 * Calculate CODE 93 checksum (modulo 47). 530 * @param string $code code to represent. 531 * @return string checksum code. 532 * @access protected 533 */ 534 protected function checksum_code93($code) { 535 $chars = array( 536 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 537 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 538 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 539 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%'); 540 // translate special characters 541 $code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%'); 542 $len = strlen($code); 543 // calculate check digit C 544 $p = 1; 545 $check = 0; 546 for ($i = ($len - 1); $i >= 0; --$i) { 547 $k = array_keys($chars, $code{$i}); 548 $check += ($k[0] * $p); 549 ++$p; 550 if ($p > 20) { 551 $p = 1; 552 } 553 } 554 $check %= 47; 555 $c = $chars[$check]; 556 $code .= $c; 557 // calculate check digit K 558 $p = 1; 559 $check = 0; 560 for ($i = $len; $i >= 0; --$i) { 561 $k = array_keys($chars, $code{$i}); 562 $check += ($k[0] * $p); 563 ++$p; 564 if ($p > 15) { 565 $p = 1; 566 } 567 } 568 $check %= 47; 569 $k = $chars[$check]; 570 return $c.$k; 571 } 572 573 /** 574 * Checksum for standard 2 of 5 barcodes. 575 * @param string $code code to process. 576 * @return int checksum. 577 * @access protected 578 */ 579 protected function checksum_s25($code) { 580 $len = strlen($code); 581 $sum = 0; 582 for ($i = 0; $i < $len; $i+=2) { 583 $sum += $code{$i}; 584 } 585 $sum *= 3; 586 for ($i = 1; $i < $len; $i+=2) { 587 $sum += ($code{$i}); 588 } 589 $r = $sum % 10; 590 if($r > 0) { 591 $r = (10 - $r); 592 } 593 return $r; 594 } 595 596 /** 597 * MSI. 598 * Variation of Plessey code, with similar applications 599 * Contains digits (0 to 9) and encodes the data only in the width of bars. 600 * @param string $code code to represent. 601 * @param boolean $checksum if true add a checksum to the code (modulo 11) 602 * @return array barcode representation. 603 * @access protected 604 */ 605 protected function barcode_msi($code, $checksum=false) { 606 $chr['0'] = '100100100100'; 607 $chr['1'] = '100100100110'; 608 $chr['2'] = '100100110100'; 609 $chr['3'] = '100100110110'; 610 $chr['4'] = '100110100100'; 611 $chr['5'] = '100110100110'; 612 $chr['6'] = '100110110100'; 613 $chr['7'] = '100110110110'; 614 $chr['8'] = '110100100100'; 615 $chr['9'] = '110100100110'; 616 $chr['A'] = '110100110100'; 617 $chr['B'] = '110100110110'; 618 $chr['C'] = '110110100100'; 619 $chr['D'] = '110110100110'; 620 $chr['E'] = '110110110100'; 621 $chr['F'] = '110110110110'; 622 if ($checksum) { 623 // add checksum 624 $clen = strlen($code); 625 $p = 2; 626 $check = 0; 627 for ($i = ($clen - 1); $i >= 0; --$i) { 628 $check += (hexdec($code{$i}) * $p); 629 ++$p; 630 if ($p > 7) { 631 $p = 2; 632 } 633 } 634 $check %= 11; 635 if ($check > 0) { 636 $check = 11 - $check; 637 } 638 $code .= $check; 639 } 640 $seq = '110'; // left guard 641 $clen = strlen($code); 642 for ($i = 0; $i < $clen; ++$i) { 643 $digit = $code{$i}; 644 if (!isset($chr[$digit])) { 645 // invalid character 646 return false; 647 } 648 $seq .= $chr[$digit]; 649 } 650 $seq .= '1001'; // right guard 651 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 652 return $this->binseq_to_array($seq, $bararray); 653 } 654 655 /** 656 * Standard 2 of 5 barcodes. 657 * Used in airline ticket marking, photofinishing 658 * Contains digits (0 to 9) and encodes the data only in the width of bars. 659 * @param string $code code to represent. 660 * @param boolean $checksum if true add a checksum to the code 661 * @return array barcode representation. 662 * @access protected 663 */ 664 protected function barcode_s25($code, $checksum=false) { 665 $chr['0'] = '10101110111010'; 666 $chr['1'] = '11101010101110'; 667 $chr['2'] = '10111010101110'; 668 $chr['3'] = '11101110101010'; 669 $chr['4'] = '10101110101110'; 670 $chr['5'] = '11101011101010'; 671 $chr['6'] = '10111011101010'; 672 $chr['7'] = '10101011101110'; 673 $chr['8'] = '10101110111010'; 674 $chr['9'] = '10111010111010'; 675 if ($checksum) { 676 // add checksum 677 $code .= $this->checksum_s25($code); 678 } 679 if((strlen($code) % 2) != 0) { 680 // add leading zero if code-length is odd 681 $code = '0'.$code; 682 } 683 $seq = '11011010'; 684 $clen = strlen($code); 685 for ($i = 0; $i < $clen; ++$i) { 686 $digit = $code{$i}; 687 if (!isset($chr[$digit])) { 688 // invalid character 689 return false; 690 } 691 $seq .= $chr[$digit]; 692 } 693 $seq .= '1101011'; 694 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 695 return $this->binseq_to_array($seq, $bararray); 696 } 697 698 /** 699 * Convert binary barcode sequence to TCPDF barcode array 700 * @param string $seq barcode as binary sequence 701 * òparam array $bararray TCPDF barcode array to fill up 702 * @return array barcode representation. 703 * @access protected 704 */ 705 protected function binseq_to_array($seq, $bararray) { 706 $len = strlen($seq); 707 $w = 0; 708 $k = 0; 709 for ($i = 0; $i < $len; ++$i) { 710 $w += 1; 711 if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) { 712 if ($seq{$i} == '1') { 713 $t = true; // bar 714 } else { 715 $t = false; // space 716 } 717 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 718 $bararray['maxw'] += $w; 719 ++$k; 720 $w = 0; 721 } 722 } 723 return $bararray; 724 } 725 726 /** 727 * Interleaved 2 of 5 barcodes. 728 * Compact numeric code, widely used in industry, air cargo 729 * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces. 730 * @param string $code code to represent. 731 * @param boolean $checksum if true add a checksum to the code 732 * @return array barcode representation. 733 * @access protected 734 */ 735 protected function barcode_i25($code, $checksum=false) { 736 $chr['0'] = '11221'; 737 $chr['1'] = '21112'; 738 $chr['2'] = '12112'; 739 $chr['3'] = '22111'; 740 $chr['4'] = '11212'; 741 $chr['5'] = '21211'; 742 $chr['6'] = '12211'; 743 $chr['7'] = '11122'; 744 $chr['8'] = '21121'; 745 $chr['9'] = '12121'; 746 $chr['A'] = '11'; 747 $chr['Z'] = '21'; 748 if ($checksum) { 749 // add checksum 750 $code .= $this->checksum_s25($code); 751 } 752 if((strlen($code) % 2) != 0) { 753 // add leading zero if code-length is odd 754 $code = '0'.$code; 755 } 756 // add start and stop codes 757 $code = 'AA'.strtolower($code).'ZA'; 758 759 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 760 $k = 0; 761 $clen = strlen($code); 762 for ($i = 0; $i < $clen; $i = ($i + 2)) { 763 $char_bar = $code{$i}; 764 $char_space = $code{$i+1}; 765 if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) { 766 // invalid character 767 return false; 768 } 769 // create a bar-space sequence 770 $seq = ''; 771 $chrlen = strlen($chr[$char_bar]); 772 for ($s = 0; $s < $chrlen; $s++){ 773 $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s}; 774 } 775 $seqlen = strlen($seq); 776 for ($j = 0; $j < $seqlen; ++$j) { 777 if (($j % 2) == 0) { 778 $t = true; // bar 779 } else { 780 $t = false; // space 781 } 782 $w = $seq{$j}; 783 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 784 $bararray['maxw'] += $w; 785 ++$k; 786 } 787 } 788 return $bararray; 789 } 790 791 /** 792 * C128 barcodes. 793 * Very capable code, excellent density, high reliability; in very wide use world-wide 794 * @param string $code code to represent. 795 * @param string $type barcode type: A, B or C 796 * @return array barcode representation. 797 * @access protected 798 */ 799 protected function barcode_c128($code, $type='B') { 800 $chr = array( 801 '212222', /* 00 */ 802 '222122', /* 01 */ 803 '222221', /* 02 */ 804 '121223', /* 03 */ 805 '121322', /* 04 */ 806 '131222', /* 05 */ 807 '122213', /* 06 */ 808 '122312', /* 07 */ 809 '132212', /* 08 */ 810 '221213', /* 09 */ 811 '221312', /* 10 */ 812 '231212', /* 11 */ 813 '112232', /* 12 */ 814 '122132', /* 13 */ 815 '122231', /* 14 */ 816 '113222', /* 15 */ 817 '123122', /* 16 */ 818 '123221', /* 17 */ 819 '223211', /* 18 */ 820 '221132', /* 19 */ 821 '221231', /* 20 */ 822 '213212', /* 21 */ 823 '223112', /* 22 */ 824 '312131', /* 23 */ 825 '311222', /* 24 */ 826 '321122', /* 25 */ 827 '321221', /* 26 */ 828 '312212', /* 27 */ 829 '322112', /* 28 */ 830 '322211', /* 29 */ 831 '212123', /* 30 */ 832 '212321', /* 31 */ 833 '232121', /* 32 */ 834 '111323', /* 33 */ 835 '131123', /* 34 */ 836 '131321', /* 35 */ 837 '112313', /* 36 */ 838 '132113', /* 37 */ 839 '132311', /* 38 */ 840 '211313', /* 39 */ 841 '231113', /* 40 */ 842 '231311', /* 41 */ 843 '112133', /* 42 */ 844 '112331', /* 43 */ 845 '132131', /* 44 */ 846 '113123', /* 45 */ 847 '113321', /* 46 */ 848 '133121', /* 47 */ 849 '313121', /* 48 */ 850 '211331', /* 49 */ 851 '231131', /* 50 */ 852 '213113', /* 51 */ 853 '213311', /* 52 */ 854 '213131', /* 53 */ 855 '311123', /* 54 */ 856 '311321', /* 55 */ 857 '331121', /* 56 */ 858 '312113', /* 57 */ 859 '312311', /* 58 */ 860 '332111', /* 59 */ 861 '314111', /* 60 */ 862 '221411', /* 61 */ 863 '431111', /* 62 */ 864 '111224', /* 63 */ 865 '111422', /* 64 */ 866 '121124', /* 65 */ 867 '121421', /* 66 */ 868 '141122', /* 67 */ 869 '141221', /* 68 */ 870 '112214', /* 69 */ 871 '112412', /* 70 */ 872 '122114', /* 71 */ 873 '122411', /* 72 */ 874 '142112', /* 73 */ 875 '142211', /* 74 */ 876 '241211', /* 75 */ 877 '221114', /* 76 */ 878 '413111', /* 77 */ 879 '241112', /* 78 */ 880 '134111', /* 79 */ 881 '111242', /* 80 */ 882 '121142', /* 81 */ 883 '121241', /* 82 */ 884 '114212', /* 83 */ 885 '124112', /* 84 */ 886 '124211', /* 85 */ 887 '411212', /* 86 */ 888 '421112', /* 87 */ 889 '421211', /* 88 */ 890 '212141', /* 89 */ 891 '214121', /* 90 */ 892 '412121', /* 91 */ 893 '111143', /* 92 */ 894 '111341', /* 93 */ 895 '131141', /* 94 */ 896 '114113', /* 95 */ 897 '114311', /* 96 */ 898 '411113', /* 97 */ 899 '411311', /* 98 */ 900 '113141', /* 99 */ 901 '114131', /* 100 */ 902 '311141', /* 101 */ 903 '411131', /* 102 */ 904 '211412', /* 103 START A */ 905 '211214', /* 104 START B */ 906 '211232', /* 105 START C */ 907 '233111', /* STOP */ 908 '200000' /* END */ 909 ); 910 $keys = ''; 911 switch(strtoupper($type)) { 912 case 'A': { 913 $startid = 103; 914 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'; 915 for ($i = 0; $i < 32; ++$i) { 916 $keys .= chr($i); 917 } 918 break; 919 } 920 case 'B': { 921 $startid = 104; 922 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127); 923 break; 924 } 925 case 'C': { 926 $startid = 105; 927 $keys = ''; 928 if ((strlen($code) % 2) != 0) { 929 // The length of barcode value must be even ($code). You must pad the number with zeros 930 return false; 931 } 932 for ($i = 0; $i <= 99; ++$i) { 933 $keys .= chr($i); 934 } 935 $new_code = ''; 936 $hclen = (strlen($code) / 2); 937 for ($i = 0; $i < $hclen; ++$i) { 938 $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)})); 939 } 940 $code = $new_code; 941 break; 942 } 943 default: { 944 return false; 945 } 946 } 947 // calculate check character 948 $sum = $startid; 949 $clen = strlen($code); 950 for ($i = 0; $i < $clen; ++$i) { 951 $sum += (strpos($keys, $code{$i}) * ($i+1)); 952 } 953 $check = ($sum % 103); 954 // add start, check and stop codes 955 $code = chr($startid).$code.chr($check).chr(106).chr(107); 956 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 957 $k = 0; 958 $len = strlen($code); 959 for ($i = 0; $i < $len; ++$i) { 960 $ck = strpos($keys, $code{$i}); 961 if (($i == 0) OR ($i > ($len-4))) { 962 $char_num = ord($code{$i}); 963 $seq = $chr[$char_num]; 964 } elseif(($ck >= 0) AND isset($chr[$ck])) { 965 $seq = $chr[$ck]; 966 } else { 967 // invalid character 968 return false; 969 } 970 for ($j = 0; $j < 6; ++$j) { 971 if (($j % 2) == 0) { 972 $t = true; // bar 973 } else { 974 $t = false; // space 975 } 976 $w = $seq{$j}; 977 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 978 $bararray['maxw'] += $w; 979 ++$k; 980 } 981 } 982 return $bararray; 983 } 984 985 /** 986 * EAN13 and UPC-A barcodes. 987 * EAN13: European Article Numbering international retail product code 988 * UPC-A: Universal product code seen on almost all retail products in the USA and Canada 989 * UPC-E: Short version of UPC symbol 990 * @param string $code code to represent. 991 * @param string $len barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A 992 * @return array barcode representation. 993 * @access protected 994 */ 995 protected function barcode_eanupc($code, $len=13) { 996 $upce = false; 997 if ($len == 6) { 998 $len = 12; // UPC-A 999 $upce = true; // UPC-E mode 1000 } 1001 $data_len = $len - 1; 1002 //Padding 1003 $code = str_pad($code, $data_len, '0', STR_PAD_LEFT); 1004 $code_len = strlen($code); 1005 // calculate check digit 1006 $sum_a = 0; 1007 for ($i = 1; $i < $data_len; $i+=2) { 1008 $sum_a += $code{$i}; 1009 } 1010 if ($len > 12) { 1011 $sum_a *= 3; 1012 } 1013 $sum_b = 0; 1014 for ($i = 0; $i < $data_len; $i+=2) { 1015 $sum_b += ($code{$i}); 1016 } 1017 if ($len < 13) { 1018 $sum_b *= 3; 1019 } 1020 $r = ($sum_a + $sum_b) % 10; 1021 if($r > 0) { 1022 $r = (10 - $r); 1023 } 1024 if ($code_len == $data_len) { 1025 // add check digit 1026 $code .= $r; 1027 } elseif ($r !== intval($code{$data_len})) { 1028 // wrong checkdigit 1029 return false; 1030 } 1031 if ($len == 12) { 1032 // UPC-A 1033 $code = '0'.$code; 1034 ++$len; 1035 } 1036 if ($upce) { 1037 // convert UPC-A to UPC-E 1038 $tmp = substr($code, 4, 3); 1039 if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) { 1040 // manufacturer code ends in 000, 100, or 200 1041 $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1); 1042 } else { 1043 $tmp = substr($code, 5, 2); 1044 if ($tmp == '00') { 1045 // manufacturer code ends in 00 1046 $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3'; 1047 } else { 1048 $tmp = substr($code, 6, 1); 1049 if ($tmp == '0') { 1050 // manufacturer code ends in 0 1051 $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4'; 1052 } else { 1053 // manufacturer code does not end in zero 1054 $upce_code = substr($code, 2, 5).substr($code, 11, 1); 1055 } 1056 } 1057 } 1058 } 1059 //Convert digits to bars 1060 $codes = array( 1061 'A'=>array( // left odd parity 1062 '0'=>'0001101', 1063 '1'=>'0011001', 1064 '2'=>'0010011', 1065 '3'=>'0111101', 1066 '4'=>'0100011', 1067 '5'=>'0110001', 1068 '6'=>'0101111', 1069 '7'=>'0111011', 1070 '8'=>'0110111', 1071 '9'=>'0001011'), 1072 'B'=>array( // left even parity 1073 '0'=>'0100111', 1074 '1'=>'0110011', 1075 '2'=>'0011011', 1076 '3'=>'0100001', 1077 '4'=>'0011101', 1078 '5'=>'0111001', 1079 '6'=>'0000101', 1080 '7'=>'0010001', 1081 '8'=>'0001001', 1082 '9'=>'0010111'), 1083 'C'=>array( // right 1084 '0'=>'1110010', 1085 '1'=>'1100110', 1086 '2'=>'1101100', 1087 '3'=>'1000010', 1088 '4'=>'1011100', 1089 '5'=>'1001110', 1090 '6'=>'1010000', 1091 '7'=>'1000100', 1092 '8'=>'1001000', 1093 '9'=>'1110100') 1094 ); 1095 $parities = array( 1096 '0'=>array('A','A','A','A','A','A'), 1097 '1'=>array('A','A','B','A','B','B'), 1098 '2'=>array('A','A','B','B','A','B'), 1099 '3'=>array('A','A','B','B','B','A'), 1100 '4'=>array('A','B','A','A','B','B'), 1101 '5'=>array('A','B','B','A','A','B'), 1102 '6'=>array('A','B','B','B','A','A'), 1103 '7'=>array('A','B','A','B','A','B'), 1104 '8'=>array('A','B','A','B','B','A'), 1105 '9'=>array('A','B','B','A','B','A') 1106 ); 1107 $upce_parities = array(); 1108 $upce_parities[0] = array( 1109 '0'=>array('B','B','B','A','A','A'), 1110 '1'=>array('B','B','A','B','A','A'), 1111 '2'=>array('B','B','A','A','B','A'), 1112 '3'=>array('B','B','A','A','A','B'), 1113 '4'=>array('B','A','B','B','A','A'), 1114 '5'=>array('B','A','A','B','B','A'), 1115 '6'=>array('B','A','A','A','B','B'), 1116 '7'=>array('B','A','B','A','B','A'), 1117 '8'=>array('B','A','B','A','A','B'), 1118 '9'=>array('B','A','A','B','A','B') 1119 ); 1120 $upce_parities[1] = array( 1121 '0'=>array('A','A','A','B','B','B'), 1122 '1'=>array('A','A','B','A','B','B'), 1123 '2'=>array('A','A','B','B','A','B'), 1124 '3'=>array('A','A','B','B','B','A'), 1125 '4'=>array('A','B','A','A','B','B'), 1126 '5'=>array('A','B','B','A','A','B'), 1127 '6'=>array('A','B','B','B','A','A'), 1128 '7'=>array('A','B','A','B','A','B'), 1129 '8'=>array('A','B','A','B','B','A'), 1130 '9'=>array('A','B','B','A','B','A') 1131 ); 1132 $k = 0; 1133 $seq = '101'; // left guard bar 1134 if ($upce) { 1135 $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1136 $p = $upce_parities[$code{1}][$r]; 1137 for ($i = 0; $i < 6; ++$i) { 1138 $seq .= $codes[$p[$i]][$upce_code{$i}]; 1139 } 1140 $seq .= '010101'; // right guard bar 1141 } else { 1142 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1143 $half_len = ceil($len / 2); 1144 if ($len == 8) { 1145 for ($i = 0; $i < $half_len; ++$i) { 1146 $seq .= $codes['A'][$code{$i}]; 1147 } 1148 } else { 1149 $p = $parities[$code{0}]; 1150 for ($i = 1; $i < $half_len; ++$i) { 1151 $seq .= $codes[$p[$i-1]][$code{$i}]; 1152 } 1153 } 1154 $seq .= '01010'; // center guard bar 1155 for ($i = $half_len; $i < $len; ++$i) { 1156 $seq .= $codes['C'][$code{$i}]; 1157 } 1158 $seq .= '101'; // right guard bar 1159 } 1160 $clen = strlen($seq); 1161 $w = 0; 1162 for ($i = 0; $i < $clen; ++$i) { 1163 $w += 1; 1164 if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) { 1165 if ($seq{$i} == '1') { 1166 $t = true; // bar 1167 } else { 1168 $t = false; // space 1169 } 1170 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 1171 $bararray['maxw'] += $w; 1172 ++$k; 1173 $w = 0; 1174 } 1175 } 1176 return $bararray; 1177 } 1178 1179 /** 1180 * UPC-Based Extentions 1181 * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers 1182 * 5-Digit Ext.: Used to mark suggested retail price of books 1183 * @param string $code code to represent. 1184 * @param string $len barcode type: 2 = 2-Digit, 5 = 5-Digit 1185 * @return array barcode representation. 1186 * @access protected 1187 */ 1188 protected function barcode_eanext($code, $len=5) { 1189 //Padding 1190 $code = str_pad($code, $len, '0', STR_PAD_LEFT); 1191 // calculate check digit 1192 if ($len == 2) { 1193 $r = $code % 4; 1194 } elseif ($len == 5) { 1195 $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3})); 1196 $r %= 10; 1197 } else { 1198 return false; 1199 } 1200 //Convert digits to bars 1201 $codes = array( 1202 'A'=>array( // left odd parity 1203 '0'=>'0001101', 1204 '1'=>'0011001', 1205 '2'=>'0010011', 1206 '3'=>'0111101', 1207 '4'=>'0100011', 1208 '5'=>'0110001', 1209 '6'=>'0101111', 1210 '7'=>'0111011', 1211 '8'=>'0110111', 1212 '9'=>'0001011'), 1213 'B'=>array( // left even parity 1214 '0'=>'0100111', 1215 '1'=>'0110011', 1216 '2'=>'0011011', 1217 '3'=>'0100001', 1218 '4'=>'0011101', 1219 '5'=>'0111001', 1220 '6'=>'0000101', 1221 '7'=>'0010001', 1222 '8'=>'0001001', 1223 '9'=>'0010111') 1224 ); 1225 $parities = array(); 1226 $parities[2] = array( 1227 '0'=>array('A','A'), 1228 '1'=>array('A','B'), 1229 '2'=>array('B','A'), 1230 '3'=>array('B','B') 1231 ); 1232 $parities[5] = array( 1233 '0'=>array('B','B','A','A','A'), 1234 '1'=>array('B','A','B','A','A'), 1235 '2'=>array('B','A','A','B','A'), 1236 '3'=>array('B','A','A','A','B'), 1237 '4'=>array('A','B','B','A','A'), 1238 '5'=>array('A','A','B','B','A'), 1239 '6'=>array('A','A','A','B','B'), 1240 '7'=>array('A','B','A','B','A'), 1241 '8'=>array('A','B','A','A','B'), 1242 '9'=>array('A','A','B','A','B') 1243 ); 1244 $p = $parities[$len][$r]; 1245 $seq = '1011'; // left guard bar 1246 $seq .= $codes[$p[0]][$code{0}]; 1247 for ($i = 1; $i < $len; ++$i) { 1248 $seq .= '01'; // separator 1249 $seq .= $codes[$p[$i]][$code{$i}]; 1250 } 1251 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1252 return $this->binseq_to_array($seq, $bararray); 1253 } 1254 1255 /** 1256 * POSTNET and PLANET barcodes. 1257 * Used by U.S. Postal Service for automated mail sorting 1258 * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD. 1259 * @param boolean $planet if true print the PLANET barcode, otherwise print POSTNET 1260 * @return array barcode representation. 1261 * @access protected 1262 */ 1263 protected function barcode_postnet($code, $planet=false) { 1264 // bar lenght 1265 if ($planet) { 1266 $barlen = Array( 1267 0 => Array(1,1,2,2,2), 1268 1 => Array(2,2,2,1,1), 1269 2 => Array(2,2,1,2,1), 1270 3 => Array(2,2,1,1,2), 1271 4 => Array(2,1,2,2,1), 1272 5 => Array(2,1,2,1,2), 1273 6 => Array(2,1,1,2,2), 1274 7 => Array(1,2,2,2,1), 1275 8 => Array(1,2,2,1,2), 1276 9 => Array(1,2,1,2,2) 1277 ); 1278 } else { 1279 $barlen = Array( 1280 0 => Array(2,2,1,1,1), 1281 1 => Array(1,1,1,2,2), 1282 2 => Array(1,1,2,1,2), 1283 3 => Array(1,1,2,2,1), 1284 4 => Array(1,2,1,1,2), 1285 5 => Array(1,2,1,2,1), 1286 6 => Array(1,2,2,1,1), 1287 7 => Array(2,1,1,1,2), 1288 8 => Array(2,1,1,2,1), 1289 9 => Array(2,1,2,1,1) 1290 ); 1291 } 1292 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array()); 1293 $k = 0; 1294 $code = str_replace('-', '', $code); 1295 $code = str_replace(' ', '', $code); 1296 $len = strlen($code); 1297 // calculate checksum 1298 $sum = 0; 1299 for ($i = 0; $i < $len; ++$i) { 1300 $sum += intval($code{$i}); 1301 } 1302 $chkd = ($sum % 10); 1303 if($chkd > 0) { 1304 $chkd = (10 - $chkd); 1305 } 1306 $code .= $chkd; 1307 $len = strlen($code); 1308 // start bar 1309 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); 1310 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1311 $bararray['maxw'] += 2; 1312 for ($i = 0; $i < $len; ++$i) { 1313 for ($j = 0; $j < 5; ++$j) { 1314 $h = $barlen[$code{$i}][$j]; 1315 $p = floor(1 / $h); 1316 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); 1317 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1318 $bararray['maxw'] += 2; 1319 } 1320 } 1321 // end bar 1322 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); 1323 $bararray['maxw'] += 1; 1324 return $bararray; 1325 } 1326 1327 /** 1328 * RMS4CC - CBC - KIX 1329 * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index) 1330 * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service. 1331 * @param string $code code to print 1332 * @param boolean $kix if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code. 1333 * @return array barcode representation. 1334 * @access protected 1335 */ 1336 protected function barcode_rms4cc($code, $kix=false) { 1337 $notkix = !$kix; 1338 // bar mode 1339 // 1 = pos 1, length 2 1340 // 2 = pos 1, length 3 1341 // 3 = pos 2, length 1 1342 // 4 = pos 2, length 2 1343 $barmode = array( 1344 '0' => array(3,3,2,2), 1345 '1' => array(3,4,1,2), 1346 '2' => array(3,4,2,1), 1347 '3' => array(4,3,1,2), 1348 '4' => array(4,3,2,1), 1349 '5' => array(4,4,1,1), 1350 '6' => array(3,1,4,2), 1351 '7' => array(3,2,3,2), 1352 '8' => array(3,2,4,1), 1353 '9' => array(4,1,3,2), 1354 'A' => array(4,1,4,1), 1355 'B' => array(4,2,3,1), 1356 'C' => array(3,1,2,4), 1357 'D' => array(3,2,1,4), 1358 'E' => array(3,2,2,3), 1359 'F' => array(4,1,1,4), 1360 'G' => array(4,1,2,3), 1361 'H' => array(4,2,1,3), 1362 'I' => array(1,3,4,2), 1363 'J' => array(1,4,3,2), 1364 'K' => array(1,4,4,1), 1365 'L' => array(2,3,3,2), 1366 'M' => array(2,3,4,1), 1367 'N' => array(2,4,3,1), 1368 'O' => array(1,3,2,4), 1369 'P' => array(1,4,1,4), 1370 'Q' => array(1,4,2,3), 1371 'R' => array(2,3,1,4), 1372 'S' => array(2,3,2,3), 1373 'T' => array(2,4,1,3), 1374 'U' => array(1,1,4,4), 1375 'V' => array(1,2,3,4), 1376 'W' => array(1,2,4,3), 1377 'X' => array(2,1,3,4), 1378 'Y' => array(2,1,4,3), 1379 'Z' => array(2,2,3,3) 1380 ); 1381 $code = strtoupper($code); 1382 $len = strlen($code); 1383 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array()); 1384 if ($notkix) { 1385 // table for checksum calculation (row,col) 1386 $checktable = array( 1387 '0' => array(1,1), 1388 '1' => array(1,2), 1389 '2' => array(1,3), 1390 '3' => array(1,4), 1391 '4' => array(1,5), 1392 '5' => array(1,0), 1393 '6' => array(2,1), 1394 '7' => array(2,2), 1395 '8' => array(2,3), 1396 '9' => array(2,4), 1397 'A' => array(2,5), 1398 'B' => array(2,0), 1399 'C' => array(3,1), 1400 'D' => array(3,2), 1401 'E' => array(3,3), 1402 'F' => array(3,4), 1403 'G' => array(3,5), 1404 'H' => array(3,0), 1405 'I' => array(4,1), 1406 'J' => array(4,2), 1407 'K' => array(4,3), 1408 'L' => array(4,4), 1409 'M' => array(4,5), 1410 'N' => array(4,0), 1411 'O' => array(5,1), 1412 'P' => array(5,2), 1413 'Q' => array(5,3), 1414 'R' => array(5,4), 1415 'S' => array(5,5), 1416 'T' => array(5,0), 1417 'U' => array(0,1), 1418 'V' => array(0,2), 1419 'W' => array(0,3), 1420 'X' => array(0,4), 1421 'Y' => array(0,5), 1422 'Z' => array(0,0) 1423 ); 1424 $row = 0; 1425 $col = 0; 1426 for ($i = 0; $i < $len; ++$i) { 1427 $row += $checktable[$code{$i}][0]; 1428 $col += $checktable[$code{$i}][1]; 1429 } 1430 $row %= 6; 1431 $col %= 6; 1432 $chk = array_keys($checktable, array($row,$col)); 1433 $code .= $chk[0]; 1434 ++$len; 1435 } 1436 $k = 0; 1437 if ($notkix) { 1438 // start bar 1439 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); 1440 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1441 $bararray['maxw'] += 2; 1442 } 1443 for ($i = 0; $i < $len; ++$i) { 1444 for ($j = 0; $j < 4; ++$j) { 1445 switch ($barmode[$code{$i}][$j]) { 1446 case 1: { 1447 $p = 0; 1448 $h = 2; 1449 break; 1450 } 1451 case 2: { 1452 $p = 0; 1453 $h = 3; 1454 break; 1455 } 1456 case 3: { 1457 $p = 1; 1458 $h = 1; 1459 break; 1460 } 1461 case 4: { 1462 $p = 1; 1463 $h = 2; 1464 break; 1465 } 1466 } 1467 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); 1468 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1469 $bararray['maxw'] += 2; 1470 } 1471 } 1472 if ($notkix) { 1473 // stop bar 1474 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0); 1475 $bararray['maxw'] += 1; 1476 } 1477 return $bararray; 1478 } 1479 1480 /** 1481 * CODABAR barcodes. 1482 * Older code often used in library systems, sometimes in blood banks 1483 * @param string $code code to represent. 1484 * @return array barcode representation. 1485 * @access protected 1486 */ 1487 protected function barcode_codabar($code) { 1488 $chr = array( 1489 '0' => '11111221', 1490 '1' => '11112211', 1491 '2' => '11121121', 1492 '3' => '22111111', 1493 '4' => '11211211', 1494 '5' => '21111211', 1495 '6' => '12111121', 1496 '7' => '12112111', 1497 '8' => '12211111', 1498 '9' => '21121111', 1499 '-' => '11122111', 1500 '$' => '11221111', 1501 ':' => '21112121', 1502 '/' => '21211121', 1503 '.' => '21212111', 1504 '+' => '11222221', 1505 'A' => '11221211', 1506 'B' => '12121121', 1507 'C' => '11121221', 1508 'D' => '11122211' 1509 ); 1510 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1511 $k = 0; 1512 $w = 0; 1513 $seq = ''; 1514 $code = 'A'.strtoupper($code).'A'; 1515 $len = strlen($code); 1516 for ($i = 0; $i < $len; ++$i) { 1517 if (!isset($chr[$code{$i}])) { 1518 return false; 1519 } 1520 $seq = $chr[$code{$i}]; 1521 for ($j = 0; $j < 8; ++$j) { 1522 if (($j % 2) == 0) { 1523 $t = true; // bar 1524 } else { 1525 $t = false; // space 1526 } 1527 $w = $seq{$j}; 1528 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 1529 $bararray['maxw'] += $w; 1530 ++$k; 1531 } 1532 } 1533 return $bararray; 1534 } 1535 1536 /** 1537 * CODE11 barcodes. 1538 * Used primarily for labeling telecommunications equipment 1539 * @param string $code code to represent. 1540 * @return array barcode representation. 1541 * @access protected 1542 */ 1543 protected function barcode_code11($code) { 1544 $chr = array( 1545 '0' => '111121', 1546 '1' => '211121', 1547 '2' => '121121', 1548 '3' => '221111', 1549 '4' => '112121', 1550 '5' => '212111', 1551 '6' => '122111', 1552 '7' => '111221', 1553 '8' => '211211', 1554 '9' => '211111', 1555 '-' => '112111', 1556 'S' => '112211' 1557 ); 1558 1559 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1560 $k = 0; 1561 $w = 0; 1562 $seq = ''; 1563 $len = strlen($code); 1564 // calculate check digit C 1565 $p = 1; 1566 $check = 0; 1567 for ($i = ($len - 1); $i >= 0; --$i) { 1568 $digit = $code{$i}; 1569 if ($digit == '-') { 1570 $dval = 10; 1571 } else { 1572 $dval = intval($digit); 1573 } 1574 $check += ($dval * $p); 1575 ++$p; 1576 if ($p > 10) { 1577 $p = 1; 1578 } 1579 } 1580 $check %= 11; 1581 if ($check == 10) { 1582 $check = '-'; 1583 } 1584 $code .= $check; 1585 if ($len > 10) { 1586 // calculate check digit K 1587 $p = 1; 1588 $check = 0; 1589 for ($i = $len; $i >= 0; --$i) { 1590 $digit = $code{$i}; 1591 if ($digit == '-') { 1592 $dval = 10; 1593 } else { 1594 $dval = intval($digit); 1595 } 1596 $check += ($dval * $p); 1597 ++$p; 1598 if ($p > 9) { 1599 $p = 1; 1600 } 1601 } 1602 $check %= 11; 1603 $code .= $check; 1604 ++$len; 1605 } 1606 $code = 'S'.$code.'S'; 1607 $len += 3; 1608 for ($i = 0; $i < $len; ++$i) { 1609 if (!isset($chr[$code{$i}])) { 1610 return false; 1611 } 1612 $seq = $chr[$code{$i}]; 1613 for ($j = 0; $j < 6; ++$j) { 1614 if (($j % 2) == 0) { 1615 $t = true; // bar 1616 } else { 1617 $t = false; // space 1618 } 1619 $w = $seq{$j}; 1620 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); 1621 $bararray['maxw'] += $w; 1622 ++$k; 1623 } 1624 } 1625 return $bararray; 1626 } 1627 1628 /** 1629 * Pharmacode 1630 * Contains digits (0 to 9) 1631 * @param string $code code to represent. 1632 * @return array barcode representation. 1633 * @access protected 1634 */ 1635 protected function barcode_pharmacode($code) { 1636 $seq = ''; 1637 $code = intval($code); 1638 while ($code > 0) { 1639 if (($code % 2) == 0) { 1640 $seq .= '11100'; 1641 $code -= 2; 1642 } else { 1643 $seq .= '100'; 1644 $code -= 1; 1645 } 1646 $code /= 2; 1647 } 1648 $seq = substr($seq, 0, -2); 1649 $seq = strrev($seq); 1650 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); 1651 return $this->binseq_to_array($seq, $bararray); 1652 } 1653 1654 /** 1655 * Pharmacode two-track 1656 * Contains digits (0 to 9) 1657 * @param string $code code to represent. 1658 * @return array barcode representation. 1659 * @access protected 1660 */ 1661 protected function barcode_pharmacode2t($code) { 1662 $seq = ''; 1663 $code = intval($code); 1664 do { 1665 switch ($code % 3) { 1666 case 0: { 1667 $seq .= '3'; 1668 $code = ($code - 3) / 3; 1669 break; 1670 } 1671 case 1: { 1672 $seq .= '1'; 1673 $code = ($code - 1) / 3; 1674 break; 1675 } 1676 case 2: { 1677 $seq .= '2'; 1678 $code = ($code - 2) / 3; 1679 break; 1680 } 1681 } 1682 } while($code != 0); 1683 $seq = strrev($seq); 1684 $k = 0; 1685 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array()); 1686 $len = strlen($seq); 1687 for ($i = 0; $i < $len; ++$i) { 1688 switch ($seq{$i}) { 1689 case '1': { 1690 $p = 1; 1691 $h = 1; 1692 break; 1693 } 1694 case '2': { 1695 $p = 0; 1696 $h = 1; 1697 break; 1698 } 1699 case '3': { 1700 $p = 0; 1701 $h = 2; 1702 break; 1703 } 1704 } 1705 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); 1706 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1707 $bararray['maxw'] += 2; 1708 } 1709 unset($bararray['bcode'][($k - 1)]); 1710 --$bararray['maxw']; 1711 return $bararray; 1712 } 1713 1714 1715 /** 1716 * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 1717 * (requires PHP bcmath extension) 1718 * Intelligent Mail barcode is a 65-bar code for use on mail in the United States. 1719 * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the presort identification that is currently printed in human readable form on the optional endorsement line (OEL) as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999. Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000- 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999, 000000000–999999999, and 00000000000–99999999999.</li></ul> 1720 * @param string $code code to print, separate the ZIP (routing code) from the rest using a minus char '-' (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode) 1721 * @return array barcode representation. 1722 * @access protected 1723 */ 1724 protected function barcode_imb($code) { 1725 $asc_chr = array(4,0,2,6,3,5,1,9,8,7,1,2,0,6,4,8,2,9,5,3,0,1,3,7,4,6,8,9,2,0,5,1,9,4,3,8,6,7,1,2,4,3,9,5,7,8,3,0,2,1,4,0,9,1,7,0,2,4,6,3,7,1,9,5,8); 1726 $dsc_chr = array(7,1,9,5,8,0,2,4,6,3,5,8,9,7,3,0,6,1,7,4,6,8,9,2,5,1,7,5,4,3,8,7,6,0,2,5,4,9,3,0,1,6,8,2,0,4,5,9,6,7,5,2,6,3,8,5,1,9,8,7,4,0,2,6,3); 1727 $asc_pos = array(3,0,8,11,1,12,8,11,10,6,4,12,2,7,9,6,7,9,2,8,4,0,12,7,10,9,0,7,10,5,7,9,6,8,2,12,1,4,2,0,1,5,4,6,12,1,0,9,4,7,5,10,2,6,9,11,2,12,6,7,5,11,0,3,2); 1728 $dsc_pos = array(2,10,12,5,9,1,5,4,3,9,11,5,10,1,6,3,4,1,10,0,2,11,8,6,1,12,3,8,6,4,4,11,0,6,1,9,11,5,3,7,3,10,7,11,8,2,10,3,5,8,0,3,12,11,8,4,5,1,3,0,7,12,9,8,10); 1729 $code_arr = explode('-', $code); 1730 $tracking_number = $code_arr[0]; 1731 if (isset($code_arr[1])) { 1732 $routing_code = $code_arr[1]; 1733 } else { 1734 $routing_code = ''; 1735 } 1736 // Conversion of Routing Code 1737 switch (strlen($routing_code)) { 1738 case 0: { 1739 $binary_code = 0; 1740 break; 1741 } 1742 case 5: { 1743 $binary_code = bcadd($routing_code, '1'); 1744 break; 1745 } 1746 case 9: { 1747 $binary_code = bcadd($routing_code, '100001'); 1748 break; 1749 } 1750 case 11: { 1751 $binary_code = bcadd($routing_code, '1000100001'); 1752 break; 1753 } 1754 default: { 1755 return false; 1756 break; 1757 } 1758 } 1759 $binary_code = bcmul($binary_code, 10); 1760 $binary_code = bcadd($binary_code, $tracking_number{0}); 1761 $binary_code = bcmul($binary_code, 5); 1762 $binary_code = bcadd($binary_code, $tracking_number{1}); 1763 $binary_code .= substr($tracking_number, 2, 18); 1764 // convert to hexadecimal 1765 $binary_code = $this->dec_to_hex($binary_code); 1766 // pad to get 13 bytes 1767 $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT); 1768 // convert string to array of bytes 1769 $binary_code_arr = chunk_split($binary_code, 2, "\r"); 1770 $binary_code_arr = substr($binary_code_arr, 0, -1); 1771 $binary_code_arr = explode("\r", $binary_code_arr); 1772 // calculate frame check sequence 1773 $fcs = $this->imb_crc11fcs($binary_code_arr); 1774 // exclude first 2 bits from first byte 1775 $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2)); 1776 $binary_code_102bit = $first_byte.substr($binary_code, 2); 1777 // convert binary data to codewords 1778 $codewords = array(); 1779 $data = $this->hex_to_dec($binary_code_102bit); 1780 $codewords[0] = bcmod($data, 636) * 2; 1781 $data = bcdiv($data, 636); 1782 for ($i = 1; $i < 9; ++$i) { 1783 $codewords[$i] = bcmod($data, 1365); 1784 $data = bcdiv($data, 1365); 1785 } 1786 $codewords[9] = $data; 1787 if (($fcs >> 10) == 1) { 1788 $codewords[9] += 659; 1789 } 1790 // generate lookup tables 1791 $table2of13 = $this->imb_tables(2, 78); 1792 $table5of13 = $this->imb_tables(5, 1287); 1793 // convert codewords to characters 1794 $characters = array(); 1795 $bitmask = 512; 1796 foreach($codewords as $k => $val) { 1797 if ($val <= 1286) { 1798 $chrcode = $table5of13[$val]; 1799 } else { 1800 $chrcode = $table2of13[($val - 1287)]; 1801 } 1802 if (($fcs & $bitmask) > 0) { 1803 // bitwise invert 1804 $chrcode = ((~$chrcode) & 8191); 1805 } 1806 $characters[] = $chrcode; 1807 $bitmask /= 2; 1808 } 1809 $characters = array_reverse($characters); 1810 // build bars 1811 $k = 0; 1812 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array()); 1813 for ($i = 0; $i < 65; ++$i) { 1814 $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0); 1815 $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0); 1816 if ($asc AND $dsc) { 1817 // full bar (F) 1818 $p = 0; 1819 $h = 3; 1820 } elseif ($asc) { 1821 // ascender (A) 1822 $p = 0; 1823 $h = 2; 1824 } elseif ($dsc) { 1825 // descender (D) 1826 $p = 1; 1827 $h = 2; 1828 } else { 1829 // tracker (T) 1830 $p = 1; 1831 $h = 1; 1832 } 1833 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); 1834 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); 1835 $bararray['maxw'] += 2; 1836 } 1837 unset($bararray['bcode'][($k - 1)]); 1838 --$bararray['maxw']; 1839 return $bararray; 1840 } 1841 1842 /** 1843 * Convert large integer number to hexadecimal representation. 1844 * (requires PHP bcmath extension) 1845 * @param string $number number to convert specified as a string 1846 * @return string hexadecimal representation 1847 */ 1848 public function dec_to_hex($number) { 1849 $i = 0; 1850 $hex = array(); 1851 if($number == 0) { 1852 return '00'; 1853 } 1854 while($number > 0) { 1855 if($number == 0) { 1856 array_push($hex, '0'); 1857 } else { 1858 array_push($hex, strtoupper(dechex(bcmod($number, '16')))); 1859 $number = bcdiv($number, '16', 0); 1860 } 1861 } 1862 $hex = array_reverse($hex); 1863 return implode($hex); 1864 } 1865 1866 /** 1867 * Convert large hexadecimal number to decimal representation (string). 1868 * (requires PHP bcmath extension) 1869 * @param string $hex hexadecimal number to convert specified as a string 1870 * @return string hexadecimal representation 1871 */ 1872 public function hex_to_dec($hex) { 1873 $dec = 0; 1874 $bitval = 1; 1875 $len = strlen($hex); 1876 for($pos = ($len - 1); $pos >= 0; --$pos) { 1877 $dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval)); 1878 $bitval = bcmul($bitval, 16); 1879 } 1880 return $dec; 1881 } 1882 1883 /** 1884 * Intelligent Mail Barcode calculation of Frame Check Sequence 1885 * @param string $code_arr array of hexadecimal values (13 bytes holding 102 bits right justified). 1886 * @return int 11 bit Frame Check Sequence as integer (decimal base) 1887 * @access protected 1888 */ 1889 protected function imb_crc11fcs($code_arr) { 1890 $genpoly = 0x0F35; // generator polynomial 1891 $fcs = 0x07FF; // Frame Check Sequence 1892 // do most significant byte skipping the 2 most significant bits 1893 $data = hexdec($code_arr[0]) << 5; 1894 for ($bit = 2; $bit < 8; ++$bit) { 1895 if (($fcs ^ $data) & 0x400) { 1896 $fcs = ($fcs << 1) ^ $genpoly; 1897 } else { 1898 $fcs = ($fcs << 1); 1899 } 1900 $fcs &= 0x7FF; 1901 $data <<= 1; 1902 } 1903 // do rest of bytes 1904 for ($byte = 1; $byte < 13; ++$byte) { 1905 $data = hexdec($code_arr[$byte]) << 3; 1906 for ($bit = 0; $bit < 8; ++$bit) { 1907 if (($fcs ^ $data) & 0x400) { 1908 $fcs = ($fcs << 1) ^ $genpoly; 1909 } else { 1910 $fcs = ($fcs << 1); 1911 } 1912 $fcs &= 0x7FF; 1913 $data <<= 1; 1914 } 1915 } 1916 return $fcs; 1917 } 1918 1919 /** 1920 * Reverse unsigned short value 1921 * @param int $num value to reversr 1922 * @return int reversed value 1923 * @access protected 1924 */ 1925 protected function imb_reverse_us($num) { 1926 $rev = 0; 1927 for ($i = 0; $i < 16; ++$i) { 1928 $rev <<= 1; 1929 $rev |= ($num & 1); 1930 $num >>= 1; 1931 } 1932 return $rev; 1933 } 1934 1935 /** 1936 * generate Nof13 tables used for Intelligent Mail Barcode 1937 * @param int $n is the type of table: 2 for 2of13 table, 5 for 5of13table 1938 * @param int $size size of table (78 for n=2 and 1287 for n=5) 1939 * @return array requested table 1940 * @access protected 1941 */ 1942 protected function imb_tables($n, $size) { 1943 $table = array(); 1944 $lli = 0; // LUT lower index 1945 $lui = $size - 1; // LUT upper index 1946 for ($count = 0; $count < 8192; ++$count) { 1947 $bit_count = 0; 1948 for ($bit_index = 0; $bit_index < 13; ++$bit_index) { 1949 $bit_count += intval(($count & (1 << $bit_index)) != 0); 1950 } 1951 // if we don't have the right number of bits on, go on to the next value 1952 if ($bit_count == $n) { 1953 $reverse = ($this->imb_reverse_us($count) >> 3); 1954 // if the reverse is less than count, we have already visited this pair before 1955 if ($reverse >= $count) { 1956 // If count is symmetric, place it at the first free slot from the end of the list. 1957 // Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list 1958 if ($reverse == $count) { 1959 $table[$lui] = $count; 1960 --$lui; 1961 } else { 1962 $table[$lli] = $count; 1963 ++$lli; 1964 $table[$lli] = $reverse; 1965 ++$lli; 1966 } 1967 } 1968 } 1969 } 1970 return $table; 1971 } 1972 1973 } // end of class 1974 1975 //============================================================+ 1976 // END OF FILE 1977 //============================================================+ 1978 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |