Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/tcpdf/barcodes.php
Go to the documentation of this file.
00001 <?php
00002 //============================================================+
00003 // File name   : barcodes.php
00004 // Version     : 1.0.021
00005 // Begin       : 2008-06-09
00006 // Last Update : 2011-09-15
00007 // Author      : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
00008 // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
00009 // -------------------------------------------------------------------
00010 // Copyright (C) 2008-2011  Nicola Asuni - Tecnick.com S.r.l.
00011 //
00012 // This file is part of TCPDF software library.
00013 //
00014 // TCPDF is free software: you can redistribute it and/or modify it
00015 // under the terms of the GNU Lesser General Public License as
00016 // published by the Free Software Foundation, either version 3 of the
00017 // License, or (at your option) any later version.
00018 //
00019 // TCPDF is distributed in the hope that it will be useful, but
00020 // WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 // See the GNU Lesser General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU Lesser General Public License
00025 // along with TCPDF.  If not, see <http://www.gnu.org/licenses/>.
00026 //
00027 // See LICENSE.TXT file for more information.
00028 // -------------------------------------------------------------------
00029 //
00030 // Description : PHP class to creates array representations for
00031 //               common 1D barcodes to be used with TCPDF.
00032 //
00033 //============================================================+
00034 
00050 class TCPDFBarcode {
00051 
00056         protected $barcode_array;
00057 
00073         public function __construct($code, $type) {
00074                 $this->setBarcode($code, $type);
00075         }
00076 
00082         public function getBarcodeArray() {
00083                 return $this->barcode_array;
00084         }
00085 
00093         public function getBarcodeSVG($w=2, $h=30, $color='black') {
00094                 // send headers
00095                 $code = $this->getBarcodeSVGcode($w, $h, $color);
00096                 header('Content-Type: application/svg+xml');
00097                 header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
00098                 header('Pragma: public');
00099                 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
00100                 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
00101                 header('Content-Disposition: inline; filename="'.md5($code).'.svg";');
00102                 //header('Content-Length: '.strlen($code));
00103                 echo $code;
00104         }
00105 
00114         public function getBarcodeSVGcode($w=2, $h=30, $color='black') {
00115                 // replace table for special characters
00116                 $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
00117                 $svg = '<'.'?'.'xml version="1.0" standalone="no"'.'?'.'>'."\n";
00118                 $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."\n";
00119                 $svg .= '<svg width="'.round(($this->barcode_array['maxw'] * $w), 3).'" height="'.$h.'" version="1.1" xmlns="http://www.w3.org/2000/svg">'."\n";
00120                 $svg .= "\t".'<desc>'.strtr($this->barcode_array['code'], $repstr).'</desc>'."\n";
00121                 $svg .= "\t".'<g id="bars" fill="'.$color.'" stroke="none">'."\n";
00122                 // print bars
00123                 $x = 0;
00124                 foreach ($this->barcode_array['bcode'] as $k => $v) {
00125                         $bw = round(($v['w'] * $w), 3);
00126                         $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
00127                         if ($v['t']) {
00128                                 $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
00129                                 // draw a vertical bar
00130                                 $svg .= "\t\t".'<rect x="'.$x.'" y="'.$y.'" width="'.$bw.'" height="'.$bh.'" />'."\n";
00131                         }
00132                         $x += $bw;
00133                 }
00134                 $svg .= "\t".'</g>'."\n";
00135                 $svg .= '</svg>'."\n";
00136                 return $svg;
00137         }
00138 
00147         public function getBarcodeHTML($w=2, $h=30, $color='black') {
00148                 // replace table for special characters
00149                 $html = '<div style="font-size:0;position:relative;">'."\n";
00150                 // print bars
00151                 $x = 0;
00152                 foreach ($this->barcode_array['bcode'] as $k => $v) {
00153                         $bw = round(($v['w'] * $w), 3);
00154                         $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
00155                         if ($v['t']) {
00156                                 $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
00157                                 // draw a vertical bar
00158                                 $html .= '<div style="background-color:'.$color.';width:'.$bw.'px;height:'.$bh.'px;position:absolute;left:'.$x.'px;top:'.$y.'px;">&nbsp;</div>'."\n";
00159                         }
00160                         $x += $bw;
00161                 }
00162                 $html .= '</div>'."\n";
00163                 return $html;
00164         }
00165 
00174         public function getBarcodePNG($w=2, $h=30, $color=array(0,0,0)) {
00175                 // calculate image size
00176                 $width = ($this->barcode_array['maxw'] * $w);
00177                 $height = $h;
00178                 if (function_exists('imagecreate')) {
00179                         // GD library
00180                         $imagick = false;
00181                         $png = imagecreate($width, $height);
00182                         $bgcol = imagecolorallocate($png, 255, 255, 255);
00183                         imagecolortransparent($png, $bgcol);
00184                         $fgcol = imagecolorallocate($png, $color[0], $color[1], $color[2]);
00185                 } elseif (extension_loaded('imagick')) {
00186                         $imagick = true;
00187                         $bgcol = new imagickpixel('rgb(255,255,255');
00188                         $fgcol = new imagickpixel('rgb('.$color[0].','.$color[1].','.$color[2].')');
00189                         $png = new Imagick();
00190                         $png->newImage($width, $height, 'none', 'png');
00191                         $bar = new imagickdraw();
00192                         $bar->setfillcolor($fgcol);
00193                 } else {
00194                         return false;
00195                 }
00196                 // print bars
00197                 $x = 0;
00198                 foreach ($this->barcode_array['bcode'] as $k => $v) {
00199                         $bw = round(($v['w'] * $w), 3);
00200                         $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
00201                         if ($v['t']) {
00202                                 $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
00203                                 // draw a vertical bar
00204                                 if ($imagick) {
00205                                         $bar->rectangle($x, $y, ($x + $bw), ($y + $bh));
00206                                 } else {
00207                                         imagefilledrectangle($png, $x, $y, ($x + $bw), ($y + $bh), $fgcol);
00208                                 }
00209                         }
00210                         $x += $bw;
00211                 }
00212                 // send headers
00213                 header('Content-Type: image/png');
00214                 header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
00215                 header('Pragma: public');
00216                 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
00217                 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
00218                 if ($imagick) {
00219                         $png->drawimage($bar);
00220                         echo $png;
00221                 } else {
00222                         imagepng($png);
00223                         imagedestroy($png);
00224                 }
00225         }
00226 
00234         public function setBarcode($code, $type) {
00235                 switch (strtoupper($type)) {
00236                         case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
00237                                 $arrcode = $this->barcode_code39($code, false, false);
00238                                 break;
00239                         }
00240                         case 'C39+': { // CODE 39 with checksum
00241                                 $arrcode = $this->barcode_code39($code, false, true);
00242                                 break;
00243                         }
00244                         case 'C39E': { // CODE 39 EXTENDED
00245                                 $arrcode = $this->barcode_code39($code, true, false);
00246                                 break;
00247                         }
00248                         case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
00249                                 $arrcode = $this->barcode_code39($code, true, true);
00250                                 break;
00251                         }
00252                         case 'C93': { // CODE 93 - USS-93
00253                                 $arrcode = $this->barcode_code93($code);
00254                                 break;
00255                         }
00256                         case 'S25': { // Standard 2 of 5
00257                                 $arrcode = $this->barcode_s25($code, false);
00258                                 break;
00259                         }
00260                         case 'S25+': { // Standard 2 of 5 + CHECKSUM
00261                                 $arrcode = $this->barcode_s25($code, true);
00262                                 break;
00263                         }
00264                         case 'I25': { // Interleaved 2 of 5
00265                                 $arrcode = $this->barcode_i25($code, false);
00266                                 break;
00267                         }
00268                         case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
00269                                 $arrcode = $this->barcode_i25($code, true);
00270                                 break;
00271                         }
00272                         case 'C128': { // CODE 128
00273                                 $arrcode = $this->barcode_c128($code, '');
00274                                 break;
00275                         }
00276                         case 'C128A': { // CODE 128 A
00277                                 $arrcode = $this->barcode_c128($code, 'A');
00278                                 break;
00279                         }
00280                         case 'C128B': { // CODE 128 B
00281                                 $arrcode = $this->barcode_c128($code, 'B');
00282                                 break;
00283                         }
00284                         case 'C128C': { // CODE 128 C
00285                                 $arrcode = $this->barcode_c128($code, 'C');
00286                                 break;
00287                         }
00288                         case 'EAN2': { // 2-Digits UPC-Based Extention
00289                                 $arrcode = $this->barcode_eanext($code, 2);
00290                                 break;
00291                         }
00292                         case 'EAN5': { // 5-Digits UPC-Based Extention
00293                                 $arrcode = $this->barcode_eanext($code, 5);
00294                                 break;
00295                         }
00296                         case 'EAN8': { // EAN 8
00297                                 $arrcode = $this->barcode_eanupc($code, 8);
00298                                 break;
00299                         }
00300                         case 'EAN13': { // EAN 13
00301                                 $arrcode = $this->barcode_eanupc($code, 13);
00302                                 break;
00303                         }
00304                         case 'UPCA': { // UPC-A
00305                                 $arrcode = $this->barcode_eanupc($code, 12);
00306                                 break;
00307                         }
00308                         case 'UPCE': { // UPC-E
00309                                 $arrcode = $this->barcode_eanupc($code, 6);
00310                                 break;
00311                         }
00312                         case 'MSI': { // MSI (Variation of Plessey code)
00313                                 $arrcode = $this->barcode_msi($code, false);
00314                                 break;
00315                         }
00316                         case 'MSI+': { // MSI + CHECKSUM (modulo 11)
00317                                 $arrcode = $this->barcode_msi($code, true);
00318                                 break;
00319                         }
00320                         case 'POSTNET': { // POSTNET
00321                                 $arrcode = $this->barcode_postnet($code, false);
00322                                 break;
00323                         }
00324                         case 'PLANET': { // PLANET
00325                                 $arrcode = $this->barcode_postnet($code, true);
00326                                 break;
00327                         }
00328                         case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
00329                                 $arrcode = $this->barcode_rms4cc($code, false);
00330                                 break;
00331                         }
00332                         case 'KIX': { // KIX (Klant index - Customer index)
00333                                 $arrcode = $this->barcode_rms4cc($code, true);
00334                                 break;
00335                         }
00336                         case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
00337                                 $arrcode = $this->barcode_imb($code);
00338                                 break;
00339                         }
00340                         case 'CODABAR': { // CODABAR
00341                                 $arrcode = $this->barcode_codabar($code);
00342                                 break;
00343                         }
00344                         case 'CODE11': { // CODE 11
00345                                 $arrcode = $this->barcode_code11($code);
00346                                 break;
00347                         }
00348                         case 'PHARMA': { // PHARMACODE
00349                                 $arrcode = $this->barcode_pharmacode($code);
00350                                 break;
00351                         }
00352                         case 'PHARMA2T': { // PHARMACODE TWO-TRACKS
00353                                 $arrcode = $this->barcode_pharmacode2t($code);
00354                                 break;
00355                         }
00356                         default: {
00357                                 $this->barcode_array = false;
00358                                 $arrcode = false;
00359                                 break;
00360                         }
00361                 }
00362                 $this->barcode_array = $arrcode;
00363         }
00364 
00374         protected function barcode_code39($code, $extended=false, $checksum=false) {
00375                 $chr['0'] = '111331311';
00376                 $chr['1'] = '311311113';
00377                 $chr['2'] = '113311113';
00378                 $chr['3'] = '313311111';
00379                 $chr['4'] = '111331113';
00380                 $chr['5'] = '311331111';
00381                 $chr['6'] = '113331111';
00382                 $chr['7'] = '111311313';
00383                 $chr['8'] = '311311311';
00384                 $chr['9'] = '113311311';
00385                 $chr['A'] = '311113113';
00386                 $chr['B'] = '113113113';
00387                 $chr['C'] = '313113111';
00388                 $chr['D'] = '111133113';
00389                 $chr['E'] = '311133111';
00390                 $chr['F'] = '113133111';
00391                 $chr['G'] = '111113313';
00392                 $chr['H'] = '311113311';
00393                 $chr['I'] = '113113311';
00394                 $chr['J'] = '111133311';
00395                 $chr['K'] = '311111133';
00396                 $chr['L'] = '113111133';
00397                 $chr['M'] = '313111131';
00398                 $chr['N'] = '111131133';
00399                 $chr['O'] = '311131131';
00400                 $chr['P'] = '113131131';
00401                 $chr['Q'] = '111111333';
00402                 $chr['R'] = '311111331';
00403                 $chr['S'] = '113111331';
00404                 $chr['T'] = '111131331';
00405                 $chr['U'] = '331111113';
00406                 $chr['V'] = '133111113';
00407                 $chr['W'] = '333111111';
00408                 $chr['X'] = '131131113';
00409                 $chr['Y'] = '331131111';
00410                 $chr['Z'] = '133131111';
00411                 $chr['-'] = '131111313';
00412                 $chr['.'] = '331111311';
00413                 $chr[' '] = '133111311';
00414                 $chr['$'] = '131313111';
00415                 $chr['/'] = '131311131';
00416                 $chr['+'] = '131113131';
00417                 $chr['%'] = '111313131';
00418                 $chr['*'] = '131131311';
00419                 $code = strtoupper($code);
00420                 if ($extended) {
00421                         // extended mode
00422                         $code = $this->encode_code39_ext($code);
00423                 }
00424                 if ($code === false) {
00425                         return false;
00426                 }
00427                 if ($checksum) {
00428                         // checksum
00429                         $code .= $this->checksum_code39($code);
00430                 }
00431                 // add start and stop codes
00432                 $code = '*'.$code.'*';
00433                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
00434                 $k = 0;
00435                 $clen = strlen($code);
00436                 for ($i = 0; $i < $clen; ++$i) {
00437                         $char = $code{$i};
00438                         if(!isset($chr[$char])) {
00439                                 // invalid character
00440                                 return false;
00441                         }
00442                         for ($j = 0; $j < 9; ++$j) {
00443                                 if (($j % 2) == 0) {
00444                                         $t = true; // bar
00445                                 } else {
00446                                         $t = false; // space
00447                                 }
00448                                 $w = $chr[$char]{$j};
00449                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
00450                                 $bararray['maxw'] += $w;
00451                                 ++$k;
00452                         }
00453                         // intercharacter gap
00454                         $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
00455                         $bararray['maxw'] += 1;
00456                         ++$k;
00457                 }
00458                 return $bararray;
00459         }
00460 
00467         protected function encode_code39_ext($code) {
00468                 $encode = array(
00469                         chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
00470                         chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
00471                         chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
00472                         chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
00473                         chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
00474                         chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
00475                         chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
00476                         chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
00477                         chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
00478                         chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
00479                         chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
00480                         chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
00481                         chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
00482                         chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
00483                         chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
00484                         chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
00485                         chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
00486                         chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
00487                         chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
00488                         chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
00489                         chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
00490                         chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
00491                         chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
00492                         chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
00493                         chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
00494                         chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
00495                         chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
00496                         chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
00497                         chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
00498                         chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
00499                         chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
00500                         chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
00501                 $code_ext = '';
00502                 $clen = strlen($code);
00503                 for ($i = 0 ; $i < $clen; ++$i) {
00504                         if (ord($code{$i}) > 127) {
00505                                 return false;
00506                         }
00507                         $code_ext .= $encode[$code{$i}];
00508                 }
00509                 return $code_ext;
00510         }
00511 
00518         protected function checksum_code39($code) {
00519                 $chars = array(
00520                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00521                         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
00522                         'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
00523                         'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
00524                 $sum = 0;
00525                 $clen = strlen($code);
00526                 for ($i = 0 ; $i < $clen; ++$i) {
00527                         $k = array_keys($chars, $code{$i});
00528                         $sum += $k[0];
00529                 }
00530                 $j = ($sum % 43);
00531                 return $chars[$j];
00532         }
00533 
00541         protected function barcode_code93($code) {
00542                 $chr[48] = '131112'; // 0
00543                 $chr[49] = '111213'; // 1
00544                 $chr[50] = '111312'; // 2
00545                 $chr[51] = '111411'; // 3
00546                 $chr[52] = '121113'; // 4
00547                 $chr[53] = '121212'; // 5
00548                 $chr[54] = '121311'; // 6
00549                 $chr[55] = '111114'; // 7
00550                 $chr[56] = '131211'; // 8
00551                 $chr[57] = '141111'; // 9
00552                 $chr[65] = '211113'; // A
00553                 $chr[66] = '211212'; // B
00554                 $chr[67] = '211311'; // C
00555                 $chr[68] = '221112'; // D
00556                 $chr[69] = '221211'; // E
00557                 $chr[70] = '231111'; // F
00558                 $chr[71] = '112113'; // G
00559                 $chr[72] = '112212'; // H
00560                 $chr[73] = '112311'; // I
00561                 $chr[74] = '122112'; // J
00562                 $chr[75] = '132111'; // K
00563                 $chr[76] = '111123'; // L
00564                 $chr[77] = '111222'; // M
00565                 $chr[78] = '111321'; // N
00566                 $chr[79] = '121122'; // O
00567                 $chr[80] = '131121'; // P
00568                 $chr[81] = '212112'; // Q
00569                 $chr[82] = '212211'; // R
00570                 $chr[83] = '211122'; // S
00571                 $chr[84] = '211221'; // T
00572                 $chr[85] = '221121'; // U
00573                 $chr[86] = '222111'; // V
00574                 $chr[87] = '112122'; // W
00575                 $chr[88] = '112221'; // X
00576                 $chr[89] = '122121'; // Y
00577                 $chr[90] = '123111'; // Z
00578                 $chr[45] = '121131'; // -
00579                 $chr[46] = '311112'; // .
00580                 $chr[32] = '311211'; //
00581                 $chr[36] = '321111'; // $
00582                 $chr[47] = '112131'; // /
00583                 $chr[43] = '113121'; // +
00584                 $chr[37] = '211131'; // %
00585                 $chr[128] = '121221'; // ($)
00586                 $chr[129] = '311121'; // (/)
00587                 $chr[130] = '122211'; // (+)
00588                 $chr[131] = '312111'; // (%)
00589                 $chr[42] = '111141'; // start-stop
00590                 $code = strtoupper($code);
00591                 $encode = array(
00592                         chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
00593                         chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
00594                         chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
00595                         chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
00596                         chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
00597                         chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
00598                         chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
00599                         chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
00600                         chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
00601                         chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
00602                         chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
00603                         chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
00604                         chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
00605                         chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
00606                         chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
00607                         chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
00608                         chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
00609                         chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
00610                         chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
00611                         chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
00612                         chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
00613                         chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
00614                         chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
00615                         chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
00616                         chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
00617                         chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
00618                         chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
00619                         chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
00620                         chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
00621                         chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
00622                         chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
00623                         chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
00624                 $code_ext = '';
00625                 $clen = strlen($code);
00626                 for ($i = 0 ; $i < $clen; ++$i) {
00627                         if (ord($code{$i}) > 127) {
00628                                 return false;
00629                         }
00630                         $code_ext .= $encode[$code{$i}];
00631                 }
00632                 // checksum
00633                 $code_ext .= $this->checksum_code93($code_ext);
00634                 // add start and stop codes
00635                 $code = '*'.$code_ext.'*';
00636                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
00637                 $k = 0;
00638                 $clen = strlen($code);
00639                 for ($i = 0; $i < $clen; ++$i) {
00640                         $char = ord($code{$i});
00641                         if(!isset($chr[$char])) {
00642                                 // invalid character
00643                                 return false;
00644                         }
00645                         for ($j = 0; $j < 6; ++$j) {
00646                                 if (($j % 2) == 0) {
00647                                         $t = true; // bar
00648                                 } else {
00649                                         $t = false; // space
00650                                 }
00651                                 $w = $chr[$char]{$j};
00652                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
00653                                 $bararray['maxw'] += $w;
00654                                 ++$k;
00655                         }
00656                 }
00657                 $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
00658                 $bararray['maxw'] += 1;
00659                 ++$k;
00660                 return $bararray;
00661         }
00662 
00669         protected function checksum_code93($code) {
00670                 $chars = array(
00671                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00672                         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
00673                         'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
00674                         'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%',
00675                         '<', '=', '>', '?');
00676                 // translate special characters
00677                 $code = strtr($code, chr(128).chr(131).chr(129).chr(130), '<=>?');
00678                 $len = strlen($code);
00679                 // calculate check digit C
00680                 $p = 1;
00681                 $check = 0;
00682                 for ($i = ($len - 1); $i >= 0; --$i) {
00683                         $k = array_keys($chars, $code{$i});
00684                         $check += ($k[0] * $p);
00685                         ++$p;
00686                         if ($p > 20) {
00687                                 $p = 1;
00688                         }
00689                 }
00690                 $check %= 47;
00691                 $c = $chars[$check];
00692                 $code .= $c;
00693                 // calculate check digit K
00694                 $p = 1;
00695                 $check = 0;
00696                 for ($i = $len; $i >= 0; --$i) {
00697                         $k = array_keys($chars, $code{$i});
00698                         $check += ($k[0] * $p);
00699                         ++$p;
00700                         if ($p > 15) {
00701                                 $p = 1;
00702                         }
00703                 }
00704                 $check %= 47;
00705                 $k = $chars[$check];
00706                 $checksum = $c.$k;
00707                 // resto respecial characters
00708                 $checksum = strtr($checksum, '<=>?', chr(128).chr(131).chr(129).chr(130));
00709                 return $checksum;
00710         }
00711 
00718         protected function checksum_s25($code) {
00719                 $len = strlen($code);
00720                 $sum = 0;
00721                 for ($i = 0; $i < $len; $i+=2) {
00722                         $sum += $code{$i};
00723                 }
00724                 $sum *= 3;
00725                 for ($i = 1; $i < $len; $i+=2) {
00726                         $sum += ($code{$i});
00727                 }
00728                 $r = $sum % 10;
00729                 if($r > 0) {
00730                         $r = (10 - $r);
00731                 }
00732                 return $r;
00733         }
00734 
00744         protected function barcode_msi($code, $checksum=false) {
00745                 $chr['0'] = '100100100100';
00746                 $chr['1'] = '100100100110';
00747                 $chr['2'] = '100100110100';
00748                 $chr['3'] = '100100110110';
00749                 $chr['4'] = '100110100100';
00750                 $chr['5'] = '100110100110';
00751                 $chr['6'] = '100110110100';
00752                 $chr['7'] = '100110110110';
00753                 $chr['8'] = '110100100100';
00754                 $chr['9'] = '110100100110';
00755                 $chr['A'] = '110100110100';
00756                 $chr['B'] = '110100110110';
00757                 $chr['C'] = '110110100100';
00758                 $chr['D'] = '110110100110';
00759                 $chr['E'] = '110110110100';
00760                 $chr['F'] = '110110110110';
00761                 if ($checksum) {
00762                         // add checksum
00763                         $clen = strlen($code);
00764                         $p = 2;
00765                         $check = 0;
00766                         for ($i = ($clen - 1); $i >= 0; --$i) {
00767                                 $check += (hexdec($code{$i}) * $p);
00768                                 ++$p;
00769                                 if ($p > 7) {
00770                                         $p = 2;
00771                                 }
00772                         }
00773                         $check %= 11;
00774                         if ($check > 0) {
00775                                 $check = 11 - $check;
00776                         }
00777                         $code .= $check;
00778                 }
00779                 $seq = '110'; // left guard
00780                 $clen = strlen($code);
00781                 for ($i = 0; $i < $clen; ++$i) {
00782                         $digit = $code{$i};
00783                         if (!isset($chr[$digit])) {
00784                                 // invalid character
00785                                 return false;
00786                         }
00787                         $seq .= $chr[$digit];
00788                 }
00789                 $seq .= '1001'; // right guard
00790                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
00791                 return $this->binseq_to_array($seq, $bararray);
00792         }
00793 
00803         protected function barcode_s25($code, $checksum=false) {
00804                 $chr['0'] = '10101110111010';
00805                 $chr['1'] = '11101010101110';
00806                 $chr['2'] = '10111010101110';
00807                 $chr['3'] = '11101110101010';
00808                 $chr['4'] = '10101110101110';
00809                 $chr['5'] = '11101011101010';
00810                 $chr['6'] = '10111011101010';
00811                 $chr['7'] = '10101011101110';
00812                 $chr['8'] = '10101110111010';
00813                 $chr['9'] = '10111010111010';
00814                 if ($checksum) {
00815                         // add checksum
00816                         $code .= $this->checksum_s25($code);
00817                 }
00818                 if((strlen($code) % 2) != 0) {
00819                         // add leading zero if code-length is odd
00820                         $code = '0'.$code;
00821                 }
00822                 $seq = '11011010';
00823                 $clen = strlen($code);
00824                 for ($i = 0; $i < $clen; ++$i) {
00825                         $digit = $code{$i};
00826                         if (!isset($chr[$digit])) {
00827                                 // invalid character
00828                                 return false;
00829                         }
00830                         $seq .= $chr[$digit];
00831                 }
00832                 $seq .= '1101011';
00833                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
00834                 return $this->binseq_to_array($seq, $bararray);
00835         }
00836 
00845         protected function binseq_to_array($seq, $bararray) {
00846                 $len = strlen($seq);
00847                 $w = 0;
00848                 $k = 0;
00849                 for ($i = 0; $i < $len; ++$i) {
00850                         $w += 1;
00851                         if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
00852                                 if ($seq{$i} == '1') {
00853                                         $t = true; // bar
00854                                 } else {
00855                                         $t = false; // space
00856                                 }
00857                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
00858                                 $bararray['maxw'] += $w;
00859                                 ++$k;
00860                                 $w = 0;
00861                         }
00862                 }
00863                 return $bararray;
00864         }
00865 
00875         protected function barcode_i25($code, $checksum=false) {
00876                 $chr['0'] = '11221';
00877                 $chr['1'] = '21112';
00878                 $chr['2'] = '12112';
00879                 $chr['3'] = '22111';
00880                 $chr['4'] = '11212';
00881                 $chr['5'] = '21211';
00882                 $chr['6'] = '12211';
00883                 $chr['7'] = '11122';
00884                 $chr['8'] = '21121';
00885                 $chr['9'] = '12121';
00886                 $chr['A'] = '11';
00887                 $chr['Z'] = '21';
00888                 if ($checksum) {
00889                         // add checksum
00890                         $code .= $this->checksum_s25($code);
00891                 }
00892                 if((strlen($code) % 2) != 0) {
00893                         // add leading zero if code-length is odd
00894                         $code = '0'.$code;
00895                 }
00896                 // add start and stop codes
00897                 $code = 'AA'.strtolower($code).'ZA';
00898 
00899                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
00900                 $k = 0;
00901                 $clen = strlen($code);
00902                 for ($i = 0; $i < $clen; $i = ($i + 2)) {
00903                         $char_bar = $code{$i};
00904                         $char_space = $code{$i+1};
00905                         if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
00906                                 // invalid character
00907                                 return false;
00908                         }
00909                         // create a bar-space sequence
00910                         $seq = '';
00911                         $chrlen = strlen($chr[$char_bar]);
00912                         for ($s = 0; $s < $chrlen; $s++){
00913                                 $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
00914                         }
00915                         $seqlen = strlen($seq);
00916                         for ($j = 0; $j < $seqlen; ++$j) {
00917                                 if (($j % 2) == 0) {
00918                                         $t = true; // bar
00919                                 } else {
00920                                         $t = false; // space
00921                                 }
00922                                 $w = $seq{$j};
00923                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
00924                                 $bararray['maxw'] += $w;
00925                                 ++$k;
00926                         }
00927                 }
00928                 return $bararray;
00929         }
00930 
00939         protected function barcode_c128($code, $type='') {
00940                 $chr = array(
00941                         '212222', /* 00 */
00942                         '222122', /* 01 */
00943                         '222221', /* 02 */
00944                         '121223', /* 03 */
00945                         '121322', /* 04 */
00946                         '131222', /* 05 */
00947                         '122213', /* 06 */
00948                         '122312', /* 07 */
00949                         '132212', /* 08 */
00950                         '221213', /* 09 */
00951                         '221312', /* 10 */
00952                         '231212', /* 11 */
00953                         '112232', /* 12 */
00954                         '122132', /* 13 */
00955                         '122231', /* 14 */
00956                         '113222', /* 15 */
00957                         '123122', /* 16 */
00958                         '123221', /* 17 */
00959                         '223211', /* 18 */
00960                         '221132', /* 19 */
00961                         '221231', /* 20 */
00962                         '213212', /* 21 */
00963                         '223112', /* 22 */
00964                         '312131', /* 23 */
00965                         '311222', /* 24 */
00966                         '321122', /* 25 */
00967                         '321221', /* 26 */
00968                         '312212', /* 27 */
00969                         '322112', /* 28 */
00970                         '322211', /* 29 */
00971                         '212123', /* 30 */
00972                         '212321', /* 31 */
00973                         '232121', /* 32 */
00974                         '111323', /* 33 */
00975                         '131123', /* 34 */
00976                         '131321', /* 35 */
00977                         '112313', /* 36 */
00978                         '132113', /* 37 */
00979                         '132311', /* 38 */
00980                         '211313', /* 39 */
00981                         '231113', /* 40 */
00982                         '231311', /* 41 */
00983                         '112133', /* 42 */
00984                         '112331', /* 43 */
00985                         '132131', /* 44 */
00986                         '113123', /* 45 */
00987                         '113321', /* 46 */
00988                         '133121', /* 47 */
00989                         '313121', /* 48 */
00990                         '211331', /* 49 */
00991                         '231131', /* 50 */
00992                         '213113', /* 51 */
00993                         '213311', /* 52 */
00994                         '213131', /* 53 */
00995                         '311123', /* 54 */
00996                         '311321', /* 55 */
00997                         '331121', /* 56 */
00998                         '312113', /* 57 */
00999                         '312311', /* 58 */
01000                         '332111', /* 59 */
01001                         '314111', /* 60 */
01002                         '221411', /* 61 */
01003                         '431111', /* 62 */
01004                         '111224', /* 63 */
01005                         '111422', /* 64 */
01006                         '121124', /* 65 */
01007                         '121421', /* 66 */
01008                         '141122', /* 67 */
01009                         '141221', /* 68 */
01010                         '112214', /* 69 */
01011                         '112412', /* 70 */
01012                         '122114', /* 71 */
01013                         '122411', /* 72 */
01014                         '142112', /* 73 */
01015                         '142211', /* 74 */
01016                         '241211', /* 75 */
01017                         '221114', /* 76 */
01018                         '413111', /* 77 */
01019                         '241112', /* 78 */
01020                         '134111', /* 79 */
01021                         '111242', /* 80 */
01022                         '121142', /* 81 */
01023                         '121241', /* 82 */
01024                         '114212', /* 83 */
01025                         '124112', /* 84 */
01026                         '124211', /* 85 */
01027                         '411212', /* 86 */
01028                         '421112', /* 87 */
01029                         '421211', /* 88 */
01030                         '212141', /* 89 */
01031                         '214121', /* 90 */
01032                         '412121', /* 91 */
01033                         '111143', /* 92 */
01034                         '111341', /* 93 */
01035                         '131141', /* 94 */
01036                         '114113', /* 95 */
01037                         '114311', /* 96 */
01038                         '411113', /* 97 */
01039                         '411311', /* 98 */
01040                         '113141', /* 99 */
01041                         '114131', /* 100 */
01042                         '311141', /* 101 */
01043                         '411131', /* 102 */
01044                         '211412', /* 103 START A */
01045                         '211214', /* 104 START B */
01046                         '211232', /* 105 START C */
01047                         '233111', /* STOP */
01048                         '200000'  /* END */
01049                 );
01050                 // ASCII characters for code A (ASCII 00 - 95)
01051                 $keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
01052                 $keys_a .= chr(0).chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8).chr(9);
01053                 $keys_a .= chr(10).chr(11).chr(12).chr(13).chr(14).chr(15).chr(16).chr(17).chr(18).chr(19);
01054                 $keys_a .= chr(20).chr(21).chr(22).chr(23).chr(24).chr(25).chr(26).chr(27).chr(28).chr(29);
01055                 $keys_a .= chr(30).chr(31);
01056                 // ASCII characters for code B (ASCII 32 - 127)
01057                 $keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
01058                 // special codes
01059                 $fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
01060                 $fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
01061                 // array of symbols
01062                 $code_data = array();
01063                 // lenght of the code
01064                 $len = strlen($code);
01065                 switch(strtoupper($type)) {
01066                         case 'A': { // MODE A
01067                                 $startid = 103;
01068                                 for ($i = 0; $i < $len; ++$i) {
01069                                         $char = $code{$i};
01070                                         $char_id = ord($char);
01071                                         if (($char_id >= 241) AND ($char_id <= 244)) {
01072                                                 $code_data[] = $fnc_a[$char_id];
01073                                         } elseif (($char_id >= 0) AND ($char_id <= 95)) {
01074                                                 $code_data[] = strpos($keys_a, $char);
01075                                         } else {
01076                                                 return false;
01077                                         }
01078                                 }
01079                                 break;
01080                         }
01081                         case 'B': { // MODE B
01082                                 $startid = 104;
01083                                 for ($i = 0; $i < $len; ++$i) {
01084                                         $char = $code{$i};
01085                                         $char_id = ord($char);
01086                                         if (($char_id >= 241) AND ($char_id <= 244)) {
01087                                                 $code_data[] = $fnc_b[$char_id];
01088                                         } elseif (($char_id >= 32) AND ($char_id <= 127)) {
01089                                                 $code_data[] = strpos($keys_b, $char);
01090                                         } else {
01091                                                 return false;
01092                                         }
01093                                 }
01094                                 break;
01095                         }
01096                         case 'C': { // MODE C
01097                                 $startid = 105;
01098                                 if (ord($code{0}) == 241) {
01099                                         $code_data[] = 102;
01100                                         $code = substr($code, 1);
01101                                         --$len;
01102                                 }
01103                                 if (($len % 2) != 0) {
01104                                         // the length must be even
01105                                         return false;
01106                                 }
01107                                 for ($i = 0; $i < $len; $i+=2) {
01108                                         $chrnum = $code{$i}.$code{$i+1};
01109                                         if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
01110                                                 $code_data[] = intval($chrnum);
01111                                         } else {
01112                                                 return false;
01113                                         }
01114                                 }
01115                                 break;
01116                         }
01117                         default: { // MODE AUTO
01118                                 // split code into sequences
01119                                 $sequence = array();
01120                                 // get numeric sequences (if any)
01121                                 $numseq = array();
01122                                 preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
01123                                 if (isset($numseq[1]) AND !empty($numseq[1])) {
01124                                         $end_offset = 0;
01125                                         foreach ($numseq[1] as $val) {
01126                                                 $offset = $val[1];
01127                                                 if ($offset > $end_offset) {
01128                                                         // non numeric sequence
01129                                                         $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset))));
01130                                                 }
01131                                                 // numeric sequence
01132                                                 $slen = strlen($val[0]);
01133                                                 if (($slen % 2) != 0) {
01134                                                         // the length must be even
01135                                                         --$slen;
01136                                                 }
01137                                                 $sequence[] = array('C', substr($code, $offset, $slen), $slen);
01138                                                 $end_offset = $offset + $slen;
01139                                         }
01140                                         if ($end_offset < $len) {
01141                                                 $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
01142                                         }
01143                                 } else {
01144                                         // text code (non C mode)
01145                                         $sequence = array_merge($sequence, $this->get128ABsequence($code));
01146                                 }
01147                                 // process the sequence
01148                                 foreach ($sequence as $key => $seq) {
01149                                         switch($seq[0]) {
01150                                                 case 'A': {
01151                                                         if ($key == 0) {
01152                                                                 $startid = 103;
01153                                                         } elseif ($sequence[($key - 1)][0] != 'A') {
01154                                                                 if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND (!isset($sequence[($key - 1)][3]))) {
01155                                                                         // single character shift
01156                                                                         $code_data[] = 98;
01157                                                                         // mark shift
01158                                                                         $sequence[$key][3] = true;
01159                                                                 } elseif (!isset($sequence[($key - 1)][3])) {
01160                                                                         $code_data[] = 101;
01161                                                                 }
01162                                                         }
01163                                                         for ($i = 0; $i < $seq[2]; ++$i) {
01164                                                                 $char = $seq[1]{$i};
01165                                                                 $char_id = ord($char);
01166                                                                 if (($char_id >= 241) AND ($char_id <= 244)) {
01167                                                                         $code_data[] = $fnc_a[$char_id];
01168                                                                 } else {
01169                                                                         $code_data[] = strpos($keys_a, $char);
01170                                                                 }
01171                                                         }
01172                                                         break;
01173                                                 }
01174                                                 case 'B': {
01175                                                         if ($key == 0) {
01176                                                                 $tmpchr = ord($seq[1]{0});
01177                                                                 if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) {
01178                                                                         switch ($sequence[($key + 1)][0]) {
01179                                                                                 case 'A': {
01180                                                                                         $startid = 103;
01181                                                                                         $sequence[$key][0] = 'A';
01182                                                                                         $code_data[] = $fnc_a[$tmpchr];
01183                                                                                         break;
01184                                                                                 }
01185                                                                                 case 'C': {
01186                                                                                         $startid = 105;
01187                                                                                         $sequence[$key][0] = 'C';
01188                                                                                         $code_data[] = $fnc_a[$tmpchr];
01189                                                                                         break;
01190                                                                                 }
01191                                                                         }
01192                                                                         break;
01193                                                                 } else {
01194                                                                         $startid = 104;
01195                                                                 }
01196                                                         } elseif ($sequence[($key - 1)][0] != 'B') {
01197                                                                 if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND (!isset($sequence[($key - 1)][3]))) {
01198                                                                         // single character shift
01199                                                                         $code_data[] = 98;
01200                                                                         // mark shift
01201                                                                         $sequence[$key][3] = true;
01202                                                                 } elseif (!isset($sequence[($key - 1)][3])) {
01203                                                                         $code_data[] = 100;
01204                                                                 }
01205                                                         }
01206                                                         for ($i = 0; $i < $seq[2]; ++$i) {
01207                                                                 $char = $seq[1]{$i};
01208                                                                 $char_id = ord($char);
01209                                                                 if (($char_id >= 241) AND ($char_id <= 244)) {
01210                                                                         $code_data[] = $fnc_b[$char_id];
01211                                                                 } else {
01212                                                                         $code_data[] = strpos($keys_b, $char);
01213                                                                 }
01214                                                         }
01215                                                         break;
01216                                                 }
01217                                                 case 'C': {
01218                                                         if ($key == 0) {
01219                                                                 $startid = 105;
01220                                                         } elseif ($sequence[($key - 1)][0] != 'C') {
01221                                                                 $code_data[] = 99;
01222                                                         }
01223                                                         for ($i = 0; $i < $seq[2]; $i+=2) {
01224                                                                 $chrnum = $seq[1]{$i}.$seq[1]{$i+1};
01225                                                                 $code_data[] = intval($chrnum);
01226                                                         }
01227                                                         break;
01228                                                 }
01229                                         }
01230                                 }
01231                         }
01232                 }
01233                 // calculate check character
01234                 $sum = $startid;
01235                 foreach ($code_data as $key => $val) {
01236                         $sum += ($val * ($key + 1));
01237                 }
01238                 // add check character
01239                 $code_data[] = ($sum % 103);
01240                 // add stop sequence
01241                 $code_data[] = 106;
01242                 $code_data[] = 107;
01243                 // add start code at the beginning
01244                 array_unshift($code_data, $startid);
01245                 // build barcode array
01246                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01247                 foreach ($code_data as $val) {
01248                         $seq = $chr[$val];
01249                         for ($j = 0; $j < 6; ++$j) {
01250                                 if (($j % 2) == 0) {
01251                                         $t = true; // bar
01252                                 } else {
01253                                         $t = false; // space
01254                                 }
01255                                 $w = $seq{$j};
01256                                 $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
01257                                 $bararray['maxw'] += $w;
01258                         }
01259                 }
01260                 return $bararray;
01261         }
01262 
01269         protected function get128ABsequence($code) {
01270                 $len = strlen($code);
01271                 $sequence = array();
01272                 // get A sequences (if any)
01273                 $numseq = array();
01274                 preg_match_all('/([\0-\31])/', $code, $numseq, PREG_OFFSET_CAPTURE);
01275                 if (isset($numseq[1]) AND !empty($numseq[1])) {
01276                         $end_offset = 0;
01277                         foreach ($numseq[1] as $val) {
01278                                 $offset = $val[1];
01279                                 if ($offset > $end_offset) {
01280                                         // B sequence
01281                                         $sequence[] = array('B', substr($code, $end_offset, ($offset - $end_offset)), ($offset - $end_offset));
01282                                 }
01283                                 // A sequence
01284                                 $slen = strlen($val[0]);
01285                                 $sequence[] = array('A', substr($code, $offset, $slen), $slen);
01286                                 $end_offset = $offset + $slen;
01287                         }
01288                         if ($end_offset < $len) {
01289                                 $sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset));
01290                         }
01291                 } else {
01292                         // only B sequence
01293                         $sequence[] = array('B', $code, $len);
01294                 }
01295                 return $sequence;
01296         }
01297 
01308         protected function barcode_eanupc($code, $len=13) {
01309                 $upce = false;
01310                 if ($len == 6) {
01311                         $len = 12; // UPC-A
01312                         $upce = true; // UPC-E mode
01313                 }
01314                 $data_len = $len - 1;
01315                 //Padding
01316                 $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
01317                 $code_len = strlen($code);
01318                 // calculate check digit
01319                 $sum_a = 0;
01320                 for ($i = 1; $i < $data_len; $i+=2) {
01321                         $sum_a += $code{$i};
01322                 }
01323                 if ($len > 12) {
01324                         $sum_a *= 3;
01325                 }
01326                 $sum_b = 0;
01327                 for ($i = 0; $i < $data_len; $i+=2) {
01328                         $sum_b += ($code{$i});
01329                 }
01330                 if ($len < 13) {
01331                         $sum_b *= 3;
01332                 }
01333                 $r = ($sum_a + $sum_b) % 10;
01334                 if($r > 0) {
01335                         $r = (10 - $r);
01336                 }
01337                 if ($code_len == $data_len) {
01338                         // add check digit
01339                         $code .= $r;
01340                 } elseif ($r !== intval($code{$data_len})) {
01341                         // wrong checkdigit
01342                         return false;
01343                 }
01344                 if ($len == 12) {
01345                         // UPC-A
01346                         $code = '0'.$code;
01347                         ++$len;
01348                 }
01349                 if ($upce) {
01350                         // convert UPC-A to UPC-E
01351                         $tmp = substr($code, 4, 3);
01352                         if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
01353                                 // manufacturer code ends in 000, 100, or 200
01354                                 $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
01355                         } else {
01356                                 $tmp = substr($code, 5, 2);
01357                                 if ($tmp == '00') {
01358                                         // manufacturer code ends in 00
01359                                         $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
01360                                 } else {
01361                                         $tmp = substr($code, 6, 1);
01362                                         if ($tmp == '0') {
01363                                                 // manufacturer code ends in 0
01364                                                 $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
01365                                         } else {
01366                                                 // manufacturer code does not end in zero
01367                                                 $upce_code = substr($code, 2, 5).substr($code, 11, 1);
01368                                         }
01369                                 }
01370                         }
01371                 }
01372                 //Convert digits to bars
01373                 $codes = array(
01374                         'A'=>array( // left odd parity
01375                                 '0'=>'0001101',
01376                                 '1'=>'0011001',
01377                                 '2'=>'0010011',
01378                                 '3'=>'0111101',
01379                                 '4'=>'0100011',
01380                                 '5'=>'0110001',
01381                                 '6'=>'0101111',
01382                                 '7'=>'0111011',
01383                                 '8'=>'0110111',
01384                                 '9'=>'0001011'),
01385                         'B'=>array( // left even parity
01386                                 '0'=>'0100111',
01387                                 '1'=>'0110011',
01388                                 '2'=>'0011011',
01389                                 '3'=>'0100001',
01390                                 '4'=>'0011101',
01391                                 '5'=>'0111001',
01392                                 '6'=>'0000101',
01393                                 '7'=>'0010001',
01394                                 '8'=>'0001001',
01395                                 '9'=>'0010111'),
01396                         'C'=>array( // right
01397                                 '0'=>'1110010',
01398                                 '1'=>'1100110',
01399                                 '2'=>'1101100',
01400                                 '3'=>'1000010',
01401                                 '4'=>'1011100',
01402                                 '5'=>'1001110',
01403                                 '6'=>'1010000',
01404                                 '7'=>'1000100',
01405                                 '8'=>'1001000',
01406                                 '9'=>'1110100')
01407                 );
01408                 $parities = array(
01409                         '0'=>array('A','A','A','A','A','A'),
01410                         '1'=>array('A','A','B','A','B','B'),
01411                         '2'=>array('A','A','B','B','A','B'),
01412                         '3'=>array('A','A','B','B','B','A'),
01413                         '4'=>array('A','B','A','A','B','B'),
01414                         '5'=>array('A','B','B','A','A','B'),
01415                         '6'=>array('A','B','B','B','A','A'),
01416                         '7'=>array('A','B','A','B','A','B'),
01417                         '8'=>array('A','B','A','B','B','A'),
01418                         '9'=>array('A','B','B','A','B','A')
01419                 );
01420                 $upce_parities = array();
01421                 $upce_parities[0] = array(
01422                         '0'=>array('B','B','B','A','A','A'),
01423                         '1'=>array('B','B','A','B','A','A'),
01424                         '2'=>array('B','B','A','A','B','A'),
01425                         '3'=>array('B','B','A','A','A','B'),
01426                         '4'=>array('B','A','B','B','A','A'),
01427                         '5'=>array('B','A','A','B','B','A'),
01428                         '6'=>array('B','A','A','A','B','B'),
01429                         '7'=>array('B','A','B','A','B','A'),
01430                         '8'=>array('B','A','B','A','A','B'),
01431                         '9'=>array('B','A','A','B','A','B')
01432                 );
01433                 $upce_parities[1] = array(
01434                         '0'=>array('A','A','A','B','B','B'),
01435                         '1'=>array('A','A','B','A','B','B'),
01436                         '2'=>array('A','A','B','B','A','B'),
01437                         '3'=>array('A','A','B','B','B','A'),
01438                         '4'=>array('A','B','A','A','B','B'),
01439                         '5'=>array('A','B','B','A','A','B'),
01440                         '6'=>array('A','B','B','B','A','A'),
01441                         '7'=>array('A','B','A','B','A','B'),
01442                         '8'=>array('A','B','A','B','B','A'),
01443                         '9'=>array('A','B','B','A','B','A')
01444                 );
01445                 $k = 0;
01446                 $seq = '101'; // left guard bar
01447                 if ($upce) {
01448                         $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01449                         $p = $upce_parities[$code{1}][$r];
01450                         for ($i = 0; $i < 6; ++$i) {
01451                                 $seq .= $codes[$p[$i]][$upce_code{$i}];
01452                         }
01453                         $seq .= '010101'; // right guard bar
01454                 } else {
01455                         $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01456                         $half_len = ceil($len / 2);
01457                         if ($len == 8) {
01458                                 for ($i = 0; $i < $half_len; ++$i) {
01459                                         $seq .= $codes['A'][$code{$i}];
01460                                 }
01461                         } else {
01462                                 $p = $parities[$code{0}];
01463                                 for ($i = 1; $i < $half_len; ++$i) {
01464                                         $seq .= $codes[$p[$i-1]][$code{$i}];
01465                                 }
01466                         }
01467                         $seq .= '01010'; // center guard bar
01468                         for ($i = $half_len; $i < $len; ++$i) {
01469                                 $seq .= $codes['C'][$code{$i}];
01470                         }
01471                         $seq .= '101'; // right guard bar
01472                 }
01473                 $clen = strlen($seq);
01474                 $w = 0;
01475                 for ($i = 0; $i < $clen; ++$i) {
01476                         $w += 1;
01477                         if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
01478                                 if ($seq{$i} == '1') {
01479                                         $t = true; // bar
01480                                 } else {
01481                                         $t = false; // space
01482                                 }
01483                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
01484                                 $bararray['maxw'] += $w;
01485                                 ++$k;
01486                                 $w = 0;
01487                         }
01488                 }
01489                 return $bararray;
01490         }
01491 
01501         protected function barcode_eanext($code, $len=5) {
01502                 //Padding
01503                 $code = str_pad($code, $len, '0', STR_PAD_LEFT);
01504                 // calculate check digit
01505                 if ($len == 2) {
01506                         $r = $code % 4;
01507                 } elseif ($len == 5) {
01508                         $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3}));
01509                         $r %= 10;
01510                 } else {
01511                         return false;
01512                 }
01513                 //Convert digits to bars
01514                 $codes = array(
01515                         'A'=>array( // left odd parity
01516                                 '0'=>'0001101',
01517                                 '1'=>'0011001',
01518                                 '2'=>'0010011',
01519                                 '3'=>'0111101',
01520                                 '4'=>'0100011',
01521                                 '5'=>'0110001',
01522                                 '6'=>'0101111',
01523                                 '7'=>'0111011',
01524                                 '8'=>'0110111',
01525                                 '9'=>'0001011'),
01526                         'B'=>array( // left even parity
01527                                 '0'=>'0100111',
01528                                 '1'=>'0110011',
01529                                 '2'=>'0011011',
01530                                 '3'=>'0100001',
01531                                 '4'=>'0011101',
01532                                 '5'=>'0111001',
01533                                 '6'=>'0000101',
01534                                 '7'=>'0010001',
01535                                 '8'=>'0001001',
01536                                 '9'=>'0010111')
01537                 );
01538                 $parities = array();
01539                 $parities[2] = array(
01540                         '0'=>array('A','A'),
01541                         '1'=>array('A','B'),
01542                         '2'=>array('B','A'),
01543                         '3'=>array('B','B')
01544                 );
01545                 $parities[5] = array(
01546                         '0'=>array('B','B','A','A','A'),
01547                         '1'=>array('B','A','B','A','A'),
01548                         '2'=>array('B','A','A','B','A'),
01549                         '3'=>array('B','A','A','A','B'),
01550                         '4'=>array('A','B','B','A','A'),
01551                         '5'=>array('A','A','B','B','A'),
01552                         '6'=>array('A','A','A','B','B'),
01553                         '7'=>array('A','B','A','B','A'),
01554                         '8'=>array('A','B','A','A','B'),
01555                         '9'=>array('A','A','B','A','B')
01556                 );
01557                 $p = $parities[$len][$r];
01558                 $seq = '1011'; // left guard bar
01559                 $seq .= $codes[$p[0]][$code{0}];
01560                 for ($i = 1; $i < $len; ++$i) {
01561                         $seq .= '01'; // separator
01562                         $seq .= $codes[$p[$i]][$code{$i}];
01563                 }
01564                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01565                 return $this->binseq_to_array($seq, $bararray);
01566         }
01567 
01576         protected function barcode_postnet($code, $planet=false) {
01577                 // bar lenght
01578                 if ($planet) {
01579                         $barlen = Array(
01580                                 0 => Array(1,1,2,2,2),
01581                                 1 => Array(2,2,2,1,1),
01582                                 2 => Array(2,2,1,2,1),
01583                                 3 => Array(2,2,1,1,2),
01584                                 4 => Array(2,1,2,2,1),
01585                                 5 => Array(2,1,2,1,2),
01586                                 6 => Array(2,1,1,2,2),
01587                                 7 => Array(1,2,2,2,1),
01588                                 8 => Array(1,2,2,1,2),
01589                                 9 => Array(1,2,1,2,2)
01590                         );
01591                 } else {
01592                         $barlen = Array(
01593                                 0 => Array(2,2,1,1,1),
01594                                 1 => Array(1,1,1,2,2),
01595                                 2 => Array(1,1,2,1,2),
01596                                 3 => Array(1,1,2,2,1),
01597                                 4 => Array(1,2,1,1,2),
01598                                 5 => Array(1,2,1,2,1),
01599                                 6 => Array(1,2,2,1,1),
01600                                 7 => Array(2,1,1,1,2),
01601                                 8 => Array(2,1,1,2,1),
01602                                 9 => Array(2,1,2,1,1)
01603                         );
01604                 }
01605                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
01606                 $k = 0;
01607                 $code = str_replace('-', '', $code);
01608                 $code = str_replace(' ', '', $code);
01609                 $len = strlen($code);
01610                 // calculate checksum
01611                 $sum = 0;
01612                 for ($i = 0; $i < $len; ++$i) {
01613                         $sum += intval($code{$i});
01614                 }
01615                 $chkd = ($sum % 10);
01616                 if($chkd > 0) {
01617                         $chkd = (10 - $chkd);
01618                 }
01619                 $code .= $chkd;
01620                 $len = strlen($code);
01621                 // start bar
01622                 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
01623                 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
01624                 $bararray['maxw'] += 2;
01625                 for ($i = 0; $i < $len; ++$i) {
01626                         for ($j = 0; $j < 5; ++$j) {
01627                                 $h = $barlen[$code{$i}][$j];
01628                                 $p = floor(1 / $h);
01629                                 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
01630                                 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
01631                                 $bararray['maxw'] += 2;
01632                         }
01633                 }
01634                 // end bar
01635                 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
01636                 $bararray['maxw'] += 1;
01637                 return $bararray;
01638         }
01639 
01649         protected function barcode_rms4cc($code, $kix=false) {
01650                 $notkix = !$kix;
01651                 // bar mode
01652                 // 1 = pos 1, length 2
01653                 // 2 = pos 1, length 3
01654                 // 3 = pos 2, length 1
01655                 // 4 = pos 2, length 2
01656                 $barmode = array(
01657                         '0' => array(3,3,2,2),
01658                         '1' => array(3,4,1,2),
01659                         '2' => array(3,4,2,1),
01660                         '3' => array(4,3,1,2),
01661                         '4' => array(4,3,2,1),
01662                         '5' => array(4,4,1,1),
01663                         '6' => array(3,1,4,2),
01664                         '7' => array(3,2,3,2),
01665                         '8' => array(3,2,4,1),
01666                         '9' => array(4,1,3,2),
01667                         'A' => array(4,1,4,1),
01668                         'B' => array(4,2,3,1),
01669                         'C' => array(3,1,2,4),
01670                         'D' => array(3,2,1,4),
01671                         'E' => array(3,2,2,3),
01672                         'F' => array(4,1,1,4),
01673                         'G' => array(4,1,2,3),
01674                         'H' => array(4,2,1,3),
01675                         'I' => array(1,3,4,2),
01676                         'J' => array(1,4,3,2),
01677                         'K' => array(1,4,4,1),
01678                         'L' => array(2,3,3,2),
01679                         'M' => array(2,3,4,1),
01680                         'N' => array(2,4,3,1),
01681                         'O' => array(1,3,2,4),
01682                         'P' => array(1,4,1,4),
01683                         'Q' => array(1,4,2,3),
01684                         'R' => array(2,3,1,4),
01685                         'S' => array(2,3,2,3),
01686                         'T' => array(2,4,1,3),
01687                         'U' => array(1,1,4,4),
01688                         'V' => array(1,2,3,4),
01689                         'W' => array(1,2,4,3),
01690                         'X' => array(2,1,3,4),
01691                         'Y' => array(2,1,4,3),
01692                         'Z' => array(2,2,3,3)
01693                 );
01694                 $code = strtoupper($code);
01695                 $len = strlen($code);
01696                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
01697                 if ($notkix) {
01698                         // table for checksum calculation (row,col)
01699                         $checktable = array(
01700                                 '0' => array(1,1),
01701                                 '1' => array(1,2),
01702                                 '2' => array(1,3),
01703                                 '3' => array(1,4),
01704                                 '4' => array(1,5),
01705                                 '5' => array(1,0),
01706                                 '6' => array(2,1),
01707                                 '7' => array(2,2),
01708                                 '8' => array(2,3),
01709                                 '9' => array(2,4),
01710                                 'A' => array(2,5),
01711                                 'B' => array(2,0),
01712                                 'C' => array(3,1),
01713                                 'D' => array(3,2),
01714                                 'E' => array(3,3),
01715                                 'F' => array(3,4),
01716                                 'G' => array(3,5),
01717                                 'H' => array(3,0),
01718                                 'I' => array(4,1),
01719                                 'J' => array(4,2),
01720                                 'K' => array(4,3),
01721                                 'L' => array(4,4),
01722                                 'M' => array(4,5),
01723                                 'N' => array(4,0),
01724                                 'O' => array(5,1),
01725                                 'P' => array(5,2),
01726                                 'Q' => array(5,3),
01727                                 'R' => array(5,4),
01728                                 'S' => array(5,5),
01729                                 'T' => array(5,0),
01730                                 'U' => array(0,1),
01731                                 'V' => array(0,2),
01732                                 'W' => array(0,3),
01733                                 'X' => array(0,4),
01734                                 'Y' => array(0,5),
01735                                 'Z' => array(0,0)
01736                         );
01737                         $row = 0;
01738                         $col = 0;
01739                         for ($i = 0; $i < $len; ++$i) {
01740                                 $row += $checktable[$code{$i}][0];
01741                                 $col += $checktable[$code{$i}][1];
01742                         }
01743                         $row %= 6;
01744                         $col %= 6;
01745                         $chk = array_keys($checktable, array($row,$col));
01746                         $code .= $chk[0];
01747                         ++$len;
01748                 }
01749                 $k = 0;
01750                 if ($notkix) {
01751                         // start bar
01752                         $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
01753                         $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
01754                         $bararray['maxw'] += 2;
01755                 }
01756                 for ($i = 0; $i < $len; ++$i) {
01757                         for ($j = 0; $j < 4; ++$j) {
01758                                 switch ($barmode[$code{$i}][$j]) {
01759                                         case 1: {
01760                                                 $p = 0;
01761                                                 $h = 2;
01762                                                 break;
01763                                         }
01764                                         case 2: {
01765                                                 $p = 0;
01766                                                 $h = 3;
01767                                                 break;
01768                                         }
01769                                         case 3: {
01770                                                 $p = 1;
01771                                                 $h = 1;
01772                                                 break;
01773                                         }
01774                                         case 4: {
01775                                                 $p = 1;
01776                                                 $h = 2;
01777                                                 break;
01778                                         }
01779                                 }
01780                                 $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
01781                                 $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
01782                                 $bararray['maxw'] += 2;
01783                         }
01784                 }
01785                 if ($notkix) {
01786                         // stop bar
01787                         $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
01788                         $bararray['maxw'] += 1;
01789                 }
01790                 return $bararray;
01791         }
01792 
01800         protected function barcode_codabar($code) {
01801                 $chr = array(
01802                         '0' => '11111221',
01803                         '1' => '11112211',
01804                         '2' => '11121121',
01805                         '3' => '22111111',
01806                         '4' => '11211211',
01807                         '5' => '21111211',
01808                         '6' => '12111121',
01809                         '7' => '12112111',
01810                         '8' => '12211111',
01811                         '9' => '21121111',
01812                         '-' => '11122111',
01813                         '$' => '11221111',
01814                         ':' => '21112121',
01815                         '/' => '21211121',
01816                         '.' => '21212111',
01817                         '+' => '11222221',
01818                         'A' => '11221211',
01819                         'B' => '12121121',
01820                         'C' => '11121221',
01821                         'D' => '11122211'
01822                 );
01823                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01824                 $k = 0;
01825                 $w = 0;
01826                 $seq = '';
01827                 $code = 'A'.strtoupper($code).'A';
01828                 $len = strlen($code);
01829                 for ($i = 0; $i < $len; ++$i) {
01830                         if (!isset($chr[$code{$i}])) {
01831                                 return false;
01832                         }
01833                         $seq = $chr[$code{$i}];
01834                         for ($j = 0; $j < 8; ++$j) {
01835                                 if (($j % 2) == 0) {
01836                                         $t = true; // bar
01837                                 } else {
01838                                         $t = false; // space
01839                                 }
01840                                 $w = $seq{$j};
01841                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
01842                                 $bararray['maxw'] += $w;
01843                                 ++$k;
01844                         }
01845                 }
01846                 return $bararray;
01847         }
01848 
01856         protected function barcode_code11($code) {
01857                 $chr = array(
01858                         '0' => '111121',
01859                         '1' => '211121',
01860                         '2' => '121121',
01861                         '3' => '221111',
01862                         '4' => '112121',
01863                         '5' => '212111',
01864                         '6' => '122111',
01865                         '7' => '111221',
01866                         '8' => '211211',
01867                         '9' => '211111',
01868                         '-' => '112111',
01869                         'S' => '112211'
01870                 );
01871                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01872                 $k = 0;
01873                 $w = 0;
01874                 $seq = '';
01875                 $len = strlen($code);
01876                 // calculate check digit C
01877                 $p = 1;
01878                 $check = 0;
01879                 for ($i = ($len - 1); $i >= 0; --$i) {
01880                         $digit = $code{$i};
01881                         if ($digit == '-') {
01882                                 $dval = 10;
01883                         } else {
01884                                 $dval = intval($digit);
01885                         }
01886                         $check += ($dval * $p);
01887                         ++$p;
01888                         if ($p > 10) {
01889                                 $p = 1;
01890                         }
01891                 }
01892                 $check %= 11;
01893                 if ($check == 10) {
01894                         $check = '-';
01895                 }
01896                 $code .= $check;
01897                 if ($len > 10) {
01898                         // calculate check digit K
01899                         $p = 1;
01900                         $check = 0;
01901                         for ($i = $len; $i >= 0; --$i) {
01902                                 $digit = $code{$i};
01903                                 if ($digit == '-') {
01904                                         $dval = 10;
01905                                 } else {
01906                                         $dval = intval($digit);
01907                                 }
01908                                 $check += ($dval * $p);
01909                                 ++$p;
01910                                 if ($p > 9) {
01911                                         $p = 1;
01912                                 }
01913                         }
01914                         $check %= 11;
01915                         $code .= $check;
01916                         ++$len;
01917                 }
01918                 $code = 'S'.$code.'S';
01919                 $len += 3;
01920                 for ($i = 0; $i < $len; ++$i) {
01921                         if (!isset($chr[$code{$i}])) {
01922                                 return false;
01923                         }
01924                         $seq = $chr[$code{$i}];
01925                         for ($j = 0; $j < 6; ++$j) {
01926                                 if (($j % 2) == 0) {
01927                                         $t = true; // bar
01928                                 } else {
01929                                         $t = false; // space
01930                                 }
01931                                 $w = $seq{$j};
01932                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
01933                                 $bararray['maxw'] += $w;
01934                                 ++$k;
01935                         }
01936                 }
01937                 return $bararray;
01938         }
01939 
01947         protected function barcode_pharmacode($code) {
01948                 $seq = '';
01949                 $code = intval($code);
01950                 while ($code > 0) {
01951                         if (($code % 2) == 0) {
01952                                 $seq .= '11100';
01953                                 $code -= 2;
01954                         } else {
01955                                 $seq .= '100';
01956                                 $code -= 1;
01957                         }
01958                         $code /= 2;
01959                 }
01960                 $seq = substr($seq, 0, -2);
01961                 $seq = strrev($seq);
01962                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
01963                 return $this->binseq_to_array($seq, $bararray);
01964         }
01965 
01973         protected function barcode_pharmacode2t($code) {
01974                 $seq = '';
01975                 $code = intval($code);
01976                 do {
01977                         switch ($code % 3) {
01978                                 case 0: {
01979                                         $seq .= '3';
01980                                         $code = ($code - 3) / 3;
01981                                         break;
01982                                 }
01983                                 case 1: {
01984                                         $seq .= '1';
01985                                         $code = ($code - 1) / 3;
01986                                         break;
01987                                 }
01988                                 case 2: {
01989                                         $seq .= '2';
01990                                         $code = ($code - 2) / 3;
01991                                         break;
01992                                 }
01993                         }
01994                 } while($code != 0);
01995                 $seq = strrev($seq);
01996                 $k = 0;
01997                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
01998                 $len = strlen($seq);
01999                 for ($i = 0; $i < $len; ++$i) {
02000                         switch ($seq{$i}) {
02001                                 case '1': {
02002                                         $p = 1;
02003                                         $h = 1;
02004                                         break;
02005                                 }
02006                                 case '2': {
02007                                         $p = 0;
02008                                         $h = 1;
02009                                         break;
02010                                 }
02011                                 case '3': {
02012                                         $p = 0;
02013                                         $h = 2;
02014                                         break;
02015                                 }
02016                         }
02017                         $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
02018                         $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
02019                         $bararray['maxw'] += 2;
02020                 }
02021                 unset($bararray['bcode'][($k - 1)]);
02022                 --$bararray['maxw'];
02023                 return $bararray;
02024         }
02025 
02026 
02036         protected function barcode_imb($code) {
02037                 $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);
02038                 $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);
02039                 $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);
02040                 $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);
02041                 $code_arr = explode('-', $code);
02042                 $tracking_number = $code_arr[0];
02043                 if (isset($code_arr[1])) {
02044                         $routing_code = $code_arr[1];
02045                 } else {
02046                         $routing_code = '';
02047                 }
02048                 // Conversion of Routing Code
02049                 switch (strlen($routing_code)) {
02050                         case 0: {
02051                                 $binary_code = 0;
02052                                 break;
02053                         }
02054                         case 5: {
02055                                 $binary_code = bcadd($routing_code, '1');
02056                                 break;
02057                         }
02058                         case 9: {
02059                                 $binary_code = bcadd($routing_code, '100001');
02060                                 break;
02061                         }
02062                         case 11: {
02063                                 $binary_code = bcadd($routing_code, '1000100001');
02064                                 break;
02065                         }
02066                         default: {
02067                                 return false;
02068                                 break;
02069                         }
02070                 }
02071                 $binary_code = bcmul($binary_code, 10);
02072                 $binary_code = bcadd($binary_code, $tracking_number{0});
02073                 $binary_code = bcmul($binary_code, 5);
02074                 $binary_code = bcadd($binary_code, $tracking_number{1});
02075                 $binary_code .= substr($tracking_number, 2, 18);
02076                 // convert to hexadecimal
02077                 $binary_code = $this->dec_to_hex($binary_code);
02078                 // pad to get 13 bytes
02079                 $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
02080                 // convert string to array of bytes
02081                 $binary_code_arr = chunk_split($binary_code, 2, "\r");
02082                 $binary_code_arr = substr($binary_code_arr, 0, -1);
02083                 $binary_code_arr = explode("\r", $binary_code_arr);
02084                 // calculate frame check sequence
02085                 $fcs = $this->imb_crc11fcs($binary_code_arr);
02086                 // exclude first 2 bits from first byte
02087                 $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
02088                 $binary_code_102bit = $first_byte.substr($binary_code, 2);
02089                 // convert binary data to codewords
02090                 $codewords = array();
02091                 $data = $this->hex_to_dec($binary_code_102bit);
02092                 $codewords[0] = bcmod($data, 636) * 2;
02093                 $data = bcdiv($data, 636);
02094                 for ($i = 1; $i < 9; ++$i) {
02095                         $codewords[$i] = bcmod($data, 1365);
02096                         $data = bcdiv($data, 1365);
02097                 }
02098                 $codewords[9] = $data;
02099                 if (($fcs >> 10) == 1) {
02100                         $codewords[9] += 659;
02101                 }
02102                 // generate lookup tables
02103                 $table2of13 = $this->imb_tables(2, 78);
02104                 $table5of13 = $this->imb_tables(5, 1287);
02105                 // convert codewords to characters
02106                 $characters = array();
02107                 $bitmask = 512;
02108                 foreach($codewords as $k => $val) {
02109                         if ($val <= 1286) {
02110                                 $chrcode = $table5of13[$val];
02111                         } else {
02112                                 $chrcode = $table2of13[($val - 1287)];
02113                         }
02114                         if (($fcs & $bitmask) > 0) {
02115                                 // bitwise invert
02116                                 $chrcode = ((~$chrcode) & 8191);
02117                         }
02118                         $characters[] = $chrcode;
02119                         $bitmask /= 2;
02120                 }
02121                 $characters = array_reverse($characters);
02122                 // build bars
02123                 $k = 0;
02124                 $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
02125                 for ($i = 0; $i < 65; ++$i) {
02126                         $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
02127                         $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
02128                         if ($asc AND $dsc) {
02129                                 // full bar (F)
02130                                 $p = 0;
02131                                 $h = 3;
02132                         } elseif ($asc) {
02133                                 // ascender (A)
02134                                 $p = 0;
02135                                 $h = 2;
02136                         } elseif ($dsc) {
02137                                 // descender (D)
02138                                 $p = 1;
02139                                 $h = 2;
02140                         } else {
02141                                 // tracker (T)
02142                                 $p = 1;
02143                                 $h = 1;
02144                         }
02145                         $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
02146                         $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
02147                         $bararray['maxw'] += 2;
02148                 }
02149                 unset($bararray['bcode'][($k - 1)]);
02150                 --$bararray['maxw'];
02151                 return $bararray;
02152         }
02153 
02160         public function dec_to_hex($number) {
02161                 $i = 0;
02162                 $hex = array();
02163                 if($number == 0) {
02164                         return '00';
02165                 }
02166                 while($number > 0) {
02167                         if($number == 0) {
02168                                 array_push($hex, '0');
02169                         } else {
02170                                 array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
02171                                 $number = bcdiv($number, '16', 0);
02172                         }
02173                 }
02174                 $hex = array_reverse($hex);
02175                 return implode($hex);
02176         }
02177 
02184         public function hex_to_dec($hex) {
02185                 $dec = 0;
02186                 $bitval = 1;
02187                 $len = strlen($hex);
02188                 for($pos = ($len - 1); $pos >= 0; --$pos) {
02189                         $dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval));
02190                         $bitval = bcmul($bitval, 16);
02191                 }
02192                 return $dec;
02193         }
02194 
02201         protected function imb_crc11fcs($code_arr) {
02202                 $genpoly = 0x0F35; // generator polynomial
02203                 $fcs = 0x07FF; // Frame Check Sequence
02204                 // do most significant byte skipping the 2 most significant bits
02205                 $data = hexdec($code_arr[0]) << 5;
02206                 for ($bit = 2; $bit < 8; ++$bit) {
02207                         if (($fcs ^ $data) & 0x400) {
02208                                 $fcs = ($fcs << 1) ^ $genpoly;
02209                         } else {
02210                                 $fcs = ($fcs << 1);
02211                         }
02212                         $fcs &= 0x7FF;
02213                         $data <<= 1;
02214                 }
02215                 // do rest of bytes
02216                 for ($byte = 1; $byte < 13; ++$byte) {
02217                         $data = hexdec($code_arr[$byte]) << 3;
02218                         for ($bit = 0; $bit < 8; ++$bit) {
02219                                 if (($fcs ^ $data) & 0x400) {
02220                                         $fcs = ($fcs << 1) ^ $genpoly;
02221                                 } else {
02222                                         $fcs = ($fcs << 1);
02223                                 }
02224                                 $fcs &= 0x7FF;
02225                                 $data <<= 1;
02226                         }
02227                 }
02228                 return $fcs;
02229         }
02230 
02237         protected function imb_reverse_us($num) {
02238                 $rev = 0;
02239                 for ($i = 0; $i < 16; ++$i) {
02240                         $rev <<= 1;
02241                         $rev |= ($num & 1);
02242                         $num >>= 1;
02243                 }
02244                 return $rev;
02245         }
02246 
02254         protected function imb_tables($n, $size) {
02255                 $table = array();
02256                 $lli = 0; // LUT lower index
02257                 $lui = $size - 1; // LUT upper index
02258                 for ($count = 0; $count < 8192; ++$count) {
02259                         $bit_count = 0;
02260                         for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
02261                                 $bit_count += intval(($count & (1 << $bit_index)) != 0);
02262                         }
02263                         // if we don't have the right number of bits on, go on to the next value
02264                         if ($bit_count == $n) {
02265                                 $reverse = ($this->imb_reverse_us($count) >> 3);
02266                                 // if the reverse is less than count, we have already visited this pair before
02267                                 if ($reverse >= $count) {
02268                                         // If count is symmetric, place it at the first free slot from the end of the list.
02269                                         // 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
02270                                         if ($reverse == $count) {
02271                                                 $table[$lui] = $count;
02272                                                 --$lui;
02273                                         } else {
02274                                                 $table[$lli] = $count;
02275                                                 ++$lli;
02276                                                 $table[$lli] = $reverse;
02277                                                 ++$lli;
02278                                         }
02279                                 }
02280                         }
02281                 }
02282                 return $table;
02283         }
02284 
02285 } // end of class
02286 //============================================================+
02287 // END OF FILE
02288 //============================================================+
 All Data Structures Namespaces Files Functions Variables Enumerations