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