tcpdf_barcodes_1d.php Quellcode

tcpdf_barcodes_1d.php
gehe zur Dokumentation dieser Datei
1 <?php
2 //============================================================+
3 // File name : tcpdf_barcodes_1d.php
4 // Version : 1.0.025
5 // Begin : 2008-06-09
6 // Last Update : 2013-03-17
7 // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
8 // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
9 // -------------------------------------------------------------------
10 // Copyright (C) 2008-2013 Nicola Asuni - Tecnick.com LTD
11 //
12 // This file is part of TCPDF software library.
13 //
14 // TCPDF is free software: you can redistribute it and/or modify it
15 // under the terms of the GNU Lesser General Public License as
16 // published by the Free Software Foundation, either version 3 of the
17 // License, or (at your option) any later version.
18 //
19 // TCPDF is distributed in the hope that it will be useful, but
20 // WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 // See the GNU Lesser General Public License for more details.
23 //
24 // You should have received a copy of the GNU Lesser General Public License
25 // along with TCPDF. If not, see <http://www.gnu.org/licenses/>.
26 //
27 // See LICENSE.TXT file for more information.
28 // -------------------------------------------------------------------
29 //
30 // Description : PHP class to creates array representations for
31 // common 1D barcodes to be used with TCPDF.
32 //
33 //============================================================+
34 
50 class TCPDFBarcode {
51 
56  protected $barcode_array;
57 
73  public function __construct($code, $type) {
74  $this->setBarcode($code, $type);
75  }
76 
82  public function getBarcodeArray() {
83  return $this->barcode_array;
84  }
85 
93  public function getBarcodeSVG($w=2, $h=30, $color='black') {
94  // send headers
95  $code = $this->getBarcodeSVGcode($w, $h, $color);
96  header('Content-Type: application/svg+xml');
97  header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
98  header('Pragma: public');
99  header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
100  header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
101  header('Content-Disposition: inline; filename="'.md5($code).'.svg";');
102  //header('Content-Length: '.strlen($code));
103  echo $code;
104  }
105 
114  public function getBarcodeSVGcode($w=2, $h=30, $color='black') {
115  // replace table for special characters
116  $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
117  $svg = '<'.'?'.'xml version="1.0" standalone="no"'.'?'.'>'."\n";
118  $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."\n";
119  $svg .= '<svg width="'.round(($this->barcode_array['maxw'] * $w), 3).'" height="'.$h.'" version="1.1" xmlns="http://www.w3.org/2000/svg">'."\n";
120  $svg .= "\t".'<desc>'.strtr($this->barcode_array['code'], $repstr).'</desc>'."\n";
121  $svg .= "\t".'<g id="bars" fill="'.$color.'" stroke="none">'."\n";
122  // print bars
123  $x = 0;
124  foreach ($this->barcode_array['bcode'] as $k => $v) {
125  $bw = round(($v['w'] * $w), 3);
126  $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
127  if ($v['t']) {
128  $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
129  // draw a vertical bar
130  $svg .= "\t\t".'<rect x="'.$x.'" y="'.$y.'" width="'.$bw.'" height="'.$bh.'" />'."\n";
131  }
132  $x += $bw;
133  }
134  $svg .= "\t".'</g>'."\n";
135  $svg .= '</svg>'."\n";
136  return $svg;
137  }
138 
147  public function getBarcodeHTML($w=2, $h=30, $color='black') {
148  $html = '<div style="font-size:0;position:relative;width:'.($this->barcode_array['maxw'] * $w).'px;height:'.($h).'px;">'."\n";
149  // print bars
150  $x = 0;
151  foreach ($this->barcode_array['bcode'] as $k => $v) {
152  $bw = round(($v['w'] * $w), 3);
153  $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
154  if ($v['t']) {
155  $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
156  // draw a vertical bar
157  $html .= '<div style="background-color:'.$color.';width:'.$bw.'px;height:'.$bh.'px;position:absolute;left:'.$x.'px;top:'.$y.'px;">&nbsp;</div>'."\n";
158  }
159  $x += $bw;
160  }
161  $html .= '</div>'."\n";
162  return $html;
163  }
164 
173  public function getBarcodePNG($w=2, $h=30, $color=array(0,0,0)) {
174  // calculate image size
175  $width = ($this->barcode_array['maxw'] * $w);
176  $height = $h;
177  if (function_exists('imagecreate')) {
178  // GD library
179  $imagick = false;
180  $png = imagecreate($width, $height);
181  $bgcol = imagecolorallocate($png, 255, 255, 255);
182  imagecolortransparent($png, $bgcol);
183  $fgcol = imagecolorallocate($png, $color[0], $color[1], $color[2]);
184  } elseif (extension_loaded('imagick')) {
185  $imagick = true;
186  $bgcol = new imagickpixel('rgb(255,255,255');
187  $fgcol = new imagickpixel('rgb('.$color[0].','.$color[1].','.$color[2].')');
188  $png = new Imagick();
189  $png->newImage($width, $height, 'none', 'png');
190  $bar = new imagickdraw();
191  $bar->setfillcolor($fgcol);
192  } else {
193  return false;
194  }
195  // print bars
196  $x = 0;
197  foreach ($this->barcode_array['bcode'] as $k => $v) {
198  $bw = round(($v['w'] * $w), 3);
199  $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3);
200  if ($v['t']) {
201  $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3);
202  // draw a vertical bar
203  if ($imagick) {
204  $bar->rectangle($x, $y, ($x + $bw - 1), ($y + $bh - 1));
205  } else {
206  imagefilledrectangle($png, $x, $y, ($x + $bw - 1), ($y + $bh - 1), $fgcol);
207  }
208  }
209  $x += $bw;
210  }
211  // send headers
212  header('Content-Type: image/png');
213  header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
214  header('Pragma: public');
215  header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
216  header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
217  if ($imagick) {
218  $png->drawimage($bar);
219  echo $png;
220  } else {
221  imagepng($png);
222  imagedestroy($png);
223  }
224  }
225 
233  public function setBarcode($code, $type) {
234  switch (strtoupper($type)) {
235  case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
236  $arrcode = $this->barcode_code39($code, false, false);
237  break;
238  }
239  case 'C39+': { // CODE 39 with checksum
240  $arrcode = $this->barcode_code39($code, false, true);
241  break;
242  }
243  case 'C39E': { // CODE 39 EXTENDED
244  $arrcode = $this->barcode_code39($code, true, false);
245  break;
246  }
247  case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
248  $arrcode = $this->barcode_code39($code, true, true);
249  break;
250  }
251  case 'C93': { // CODE 93 - USS-93
252  $arrcode = $this->barcode_code93($code);
253  break;
254  }
255  case 'S25': { // Standard 2 of 5
256  $arrcode = $this->barcode_s25($code, false);
257  break;
258  }
259  case 'S25+': { // Standard 2 of 5 + CHECKSUM
260  $arrcode = $this->barcode_s25($code, true);
261  break;
262  }
263  case 'I25': { // Interleaved 2 of 5
264  $arrcode = $this->barcode_i25($code, false);
265  break;
266  }
267  case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
268  $arrcode = $this->barcode_i25($code, true);
269  break;
270  }
271  case 'C128': { // CODE 128
272  $arrcode = $this->barcode_c128($code, '');
273  break;
274  }
275  case 'C128A': { // CODE 128 A
276  $arrcode = $this->barcode_c128($code, 'A');
277  break;
278  }
279  case 'C128B': { // CODE 128 B
280  $arrcode = $this->barcode_c128($code, 'B');
281  break;
282  }
283  case 'C128C': { // CODE 128 C
284  $arrcode = $this->barcode_c128($code, 'C');
285  break;
286  }
287  case 'EAN2': { // 2-Digits UPC-Based Extention
288  $arrcode = $this->barcode_eanext($code, 2);
289  break;
290  }
291  case 'EAN5': { // 5-Digits UPC-Based Extention
292  $arrcode = $this->barcode_eanext($code, 5);
293  break;
294  }
295  case 'EAN8': { // EAN 8
296  $arrcode = $this->barcode_eanupc($code, 8);
297  break;
298  }
299  case 'EAN13': { // EAN 13
300  $arrcode = $this->barcode_eanupc($code, 13);
301  break;
302  }
303  case 'UPCA': { // UPC-A
304  $arrcode = $this->barcode_eanupc($code, 12);
305  break;
306  }
307  case 'UPCE': { // UPC-E
308  $arrcode = $this->barcode_eanupc($code, 6);
309  break;
310  }
311  case 'MSI': { // MSI (Variation of Plessey code)
312  $arrcode = $this->barcode_msi($code, false);
313  break;
314  }
315  case 'MSI+': { // MSI + CHECKSUM (modulo 11)
316  $arrcode = $this->barcode_msi($code, true);
317  break;
318  }
319  case 'POSTNET': { // POSTNET
320  $arrcode = $this->barcode_postnet($code, false);
321  break;
322  }
323  case 'PLANET': { // PLANET
324  $arrcode = $this->barcode_postnet($code, true);
325  break;
326  }
327  case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
328  $arrcode = $this->barcode_rms4cc($code, false);
329  break;
330  }
331  case 'KIX': { // KIX (Klant index - Customer index)
332  $arrcode = $this->barcode_rms4cc($code, true);
333  break;
334  }
335  case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
336  $arrcode = $this->barcode_imb($code);
337  break;
338  }
339  case 'CODABAR': { // CODABAR
340  $arrcode = $this->barcode_codabar($code);
341  break;
342  }
343  case 'CODE11': { // CODE 11
344  $arrcode = $this->barcode_code11($code);
345  break;
346  }
347  case 'PHARMA': { // PHARMACODE
348  $arrcode = $this->barcode_pharmacode($code);
349  break;
350  }
351  case 'PHARMA2T': { // PHARMACODE TWO-TRACKS
352  $arrcode = $this->barcode_pharmacode2t($code);
353  break;
354  }
355  default: {
356  $this->barcode_array = false;
357  $arrcode = false;
358  break;
359  }
360  }
361  $this->barcode_array = $arrcode;
362  }
363 
373  protected function barcode_code39($code, $extended=false, $checksum=false) {
374  $chr['0'] = '111331311';
375  $chr['1'] = '311311113';
376  $chr['2'] = '113311113';
377  $chr['3'] = '313311111';
378  $chr['4'] = '111331113';
379  $chr['5'] = '311331111';
380  $chr['6'] = '113331111';
381  $chr['7'] = '111311313';
382  $chr['8'] = '311311311';
383  $chr['9'] = '113311311';
384  $chr['A'] = '311113113';
385  $chr['B'] = '113113113';
386  $chr['C'] = '313113111';
387  $chr['D'] = '111133113';
388  $chr['E'] = '311133111';
389  $chr['F'] = '113133111';
390  $chr['G'] = '111113313';
391  $chr['H'] = '311113311';
392  $chr['I'] = '113113311';
393  $chr['J'] = '111133311';
394  $chr['K'] = '311111133';
395  $chr['L'] = '113111133';
396  $chr['M'] = '313111131';
397  $chr['N'] = '111131133';
398  $chr['O'] = '311131131';
399  $chr['P'] = '113131131';
400  $chr['Q'] = '111111333';
401  $chr['R'] = '311111331';
402  $chr['S'] = '113111331';
403  $chr['T'] = '111131331';
404  $chr['U'] = '331111113';
405  $chr['V'] = '133111113';
406  $chr['W'] = '333111111';
407  $chr['X'] = '131131113';
408  $chr['Y'] = '331131111';
409  $chr['Z'] = '133131111';
410  $chr['-'] = '131111313';
411  $chr['.'] = '331111311';
412  $chr[' '] = '133111311';
413  $chr['$'] = '131313111';
414  $chr['/'] = '131311131';
415  $chr['+'] = '131113131';
416  $chr['%'] = '111313131';
417  $chr['*'] = '131131311';
418  $code = strtoupper($code);
419  if ($extended) {
420  // extended mode
421  $code = $this->encode_code39_ext($code);
422  }
423  if ($code === false) {
424  return false;
425  }
426  if ($checksum) {
427  // checksum
428  $code .= $this->checksum_code39($code);
429  }
430  // add start and stop codes
431  $code = '*'.$code.'*';
432  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
433  $k = 0;
434  $clen = strlen($code);
435  for ($i = 0; $i < $clen; ++$i) {
436  $char = $code{$i};
437  if(!isset($chr[$char])) {
438  // invalid character
439  return false;
440  }
441  for ($j = 0; $j < 9; ++$j) {
442  if (($j % 2) == 0) {
443  $t = true; // bar
444  } else {
445  $t = false; // space
446  }
447  $w = $chr[$char]{$j};
448  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
449  $bararray['maxw'] += $w;
450  ++$k;
451  }
452  // intercharacter gap
453  $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
454  $bararray['maxw'] += 1;
455  ++$k;
456  }
457  return $bararray;
458  }
459 
466  protected function encode_code39_ext($code) {
467  $encode = array(
468  chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
469  chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
470  chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
471  chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
472  chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
473  chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
474  chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
475  chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
476  chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
477  chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
478  chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
479  chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
480  chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
481  chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
482  chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
483  chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
484  chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
485  chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
486  chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
487  chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
488  chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
489  chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
490  chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
491  chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
492  chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
493  chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
494  chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
495  chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
496  chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
497  chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
498  chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
499  chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
500  $code_ext = '';
501  $clen = strlen($code);
502  for ($i = 0 ; $i < $clen; ++$i) {
503  if (ord($code{$i}) > 127) {
504  return false;
505  }
506  $code_ext .= $encode[$code{$i}];
507  }
508  return $code_ext;
509  }
510 
517  protected function checksum_code39($code) {
518  $chars = array(
519  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
520  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
521  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
522  'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
523  $sum = 0;
524  $clen = strlen($code);
525  for ($i = 0 ; $i < $clen; ++$i) {
526  $k = array_keys($chars, $code{$i});
527  $sum += $k[0];
528  }
529  $j = ($sum % 43);
530  return $chars[$j];
531  }
532 
540  protected function barcode_code93($code) {
541  $chr[48] = '131112'; // 0
542  $chr[49] = '111213'; // 1
543  $chr[50] = '111312'; // 2
544  $chr[51] = '111411'; // 3
545  $chr[52] = '121113'; // 4
546  $chr[53] = '121212'; // 5
547  $chr[54] = '121311'; // 6
548  $chr[55] = '111114'; // 7
549  $chr[56] = '131211'; // 8
550  $chr[57] = '141111'; // 9
551  $chr[65] = '211113'; // A
552  $chr[66] = '211212'; // B
553  $chr[67] = '211311'; // C
554  $chr[68] = '221112'; // D
555  $chr[69] = '221211'; // E
556  $chr[70] = '231111'; // F
557  $chr[71] = '112113'; // G
558  $chr[72] = '112212'; // H
559  $chr[73] = '112311'; // I
560  $chr[74] = '122112'; // J
561  $chr[75] = '132111'; // K
562  $chr[76] = '111123'; // L
563  $chr[77] = '111222'; // M
564  $chr[78] = '111321'; // N
565  $chr[79] = '121122'; // O
566  $chr[80] = '131121'; // P
567  $chr[81] = '212112'; // Q
568  $chr[82] = '212211'; // R
569  $chr[83] = '211122'; // S
570  $chr[84] = '211221'; // T
571  $chr[85] = '221121'; // U
572  $chr[86] = '222111'; // V
573  $chr[87] = '112122'; // W
574  $chr[88] = '112221'; // X
575  $chr[89] = '122121'; // Y
576  $chr[90] = '123111'; // Z
577  $chr[45] = '121131'; // -
578  $chr[46] = '311112'; // .
579  $chr[32] = '311211'; //
580  $chr[36] = '321111'; // $
581  $chr[47] = '112131'; // /
582  $chr[43] = '113121'; // +
583  $chr[37] = '211131'; // %
584  $chr[128] = '121221'; // ($)
585  $chr[129] = '311121'; // (/)
586  $chr[130] = '122211'; // (+)
587  $chr[131] = '312111'; // (%)
588  $chr[42] = '111141'; // start-stop
589  $code = strtoupper($code);
590  $encode = array(
591  chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
592  chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
593  chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
594  chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
595  chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
596  chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
597  chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
598  chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
599  chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
600  chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
601  chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
602  chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
603  chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
604  chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
605  chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
606  chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
607  chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
608  chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
609  chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
610  chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
611  chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
612  chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
613  chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
614  chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
615  chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
616  chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
617  chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
618  chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
619  chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
620  chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
621  chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
622  chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
623  $code_ext = '';
624  $clen = strlen($code);
625  for ($i = 0 ; $i < $clen; ++$i) {
626  if (ord($code{$i}) > 127) {
627  return false;
628  }
629  $code_ext .= $encode[$code{$i}];
630  }
631  // checksum
632  $code_ext .= $this->checksum_code93($code_ext);
633  // add start and stop codes
634  $code = '*'.$code_ext.'*';
635  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
636  $k = 0;
637  $clen = strlen($code);
638  for ($i = 0; $i < $clen; ++$i) {
639  $char = ord($code{$i});
640  if(!isset($chr[$char])) {
641  // invalid character
642  return false;
643  }
644  for ($j = 0; $j < 6; ++$j) {
645  if (($j % 2) == 0) {
646  $t = true; // bar
647  } else {
648  $t = false; // space
649  }
650  $w = $chr[$char]{$j};
651  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
652  $bararray['maxw'] += $w;
653  ++$k;
654  }
655  }
656  $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
657  $bararray['maxw'] += 1;
658  ++$k;
659  return $bararray;
660  }
661 
668  protected function checksum_code93($code) {
669  $chars = array(
670  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
671  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
672  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
673  'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%',
674  '<', '=', '>', '?');
675  // translate special characters
676  $code = strtr($code, chr(128).chr(131).chr(129).chr(130), '<=>?');
677  $len = strlen($code);
678  // calculate check digit C
679  $p = 1;
680  $check = 0;
681  for ($i = ($len - 1); $i >= 0; --$i) {
682  $k = array_keys($chars, $code{$i});
683  $check += ($k[0] * $p);
684  ++$p;
685  if ($p > 20) {
686  $p = 1;
687  }
688  }
689  $check %= 47;
690  $c = $chars[$check];
691  $code .= $c;
692  // calculate check digit K
693  $p = 1;
694  $check = 0;
695  for ($i = $len; $i >= 0; --$i) {
696  $k = array_keys($chars, $code{$i});
697  $check += ($k[0] * $p);
698  ++$p;
699  if ($p > 15) {
700  $p = 1;
701  }
702  }
703  $check %= 47;
704  $k = $chars[$check];
705  $checksum = $c.$k;
706  // resto respecial characters
707  $checksum = strtr($checksum, '<=>?', chr(128).chr(131).chr(129).chr(130));
708  return $checksum;
709  }
710 
717  protected function checksum_s25($code) {
718  $len = strlen($code);
719  $sum = 0;
720  for ($i = 0; $i < $len; $i+=2) {
721  $sum += $code{$i};
722  }
723  $sum *= 3;
724  for ($i = 1; $i < $len; $i+=2) {
725  $sum += ($code{$i});
726  }
727  $r = $sum % 10;
728  if($r > 0) {
729  $r = (10 - $r);
730  }
731  return $r;
732  }
733 
743  protected function barcode_msi($code, $checksum=false) {
744  $chr['0'] = '100100100100';
745  $chr['1'] = '100100100110';
746  $chr['2'] = '100100110100';
747  $chr['3'] = '100100110110';
748  $chr['4'] = '100110100100';
749  $chr['5'] = '100110100110';
750  $chr['6'] = '100110110100';
751  $chr['7'] = '100110110110';
752  $chr['8'] = '110100100100';
753  $chr['9'] = '110100100110';
754  $chr['A'] = '110100110100';
755  $chr['B'] = '110100110110';
756  $chr['C'] = '110110100100';
757  $chr['D'] = '110110100110';
758  $chr['E'] = '110110110100';
759  $chr['F'] = '110110110110';
760  if ($checksum) {
761  // add checksum
762  $clen = strlen($code);
763  $p = 2;
764  $check = 0;
765  for ($i = ($clen - 1); $i >= 0; --$i) {
766  $check += (hexdec($code{$i}) * $p);
767  ++$p;
768  if ($p > 7) {
769  $p = 2;
770  }
771  }
772  $check %= 11;
773  if ($check > 0) {
774  $check = 11 - $check;
775  }
776  $code .= $check;
777  }
778  $seq = '110'; // left guard
779  $clen = strlen($code);
780  for ($i = 0; $i < $clen; ++$i) {
781  $digit = $code{$i};
782  if (!isset($chr[$digit])) {
783  // invalid character
784  return false;
785  }
786  $seq .= $chr[$digit];
787  }
788  $seq .= '1001'; // right guard
789  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
790  return $this->binseq_to_array($seq, $bararray);
791  }
792 
802  protected function barcode_s25($code, $checksum=false) {
803  $chr['0'] = '10101110111010';
804  $chr['1'] = '11101010101110';
805  $chr['2'] = '10111010101110';
806  $chr['3'] = '11101110101010';
807  $chr['4'] = '10101110101110';
808  $chr['5'] = '11101011101010';
809  $chr['6'] = '10111011101010';
810  $chr['7'] = '10101011101110';
811  $chr['8'] = '10101110111010';
812  $chr['9'] = '10111010111010';
813  if ($checksum) {
814  // add checksum
815  $code .= $this->checksum_s25($code);
816  }
817  if((strlen($code) % 2) != 0) {
818  // add leading zero if code-length is odd
819  $code = '0'.$code;
820  }
821  $seq = '11011010';
822  $clen = strlen($code);
823  for ($i = 0; $i < $clen; ++$i) {
824  $digit = $code{$i};
825  if (!isset($chr[$digit])) {
826  // invalid character
827  return false;
828  }
829  $seq .= $chr[$digit];
830  }
831  $seq .= '1101011';
832  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
833  return $this->binseq_to_array($seq, $bararray);
834  }
835 
844  protected function binseq_to_array($seq, $bararray) {
845  $len = strlen($seq);
846  $w = 0;
847  $k = 0;
848  for ($i = 0; $i < $len; ++$i) {
849  $w += 1;
850  if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
851  if ($seq{$i} == '1') {
852  $t = true; // bar
853  } else {
854  $t = false; // space
855  }
856  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
857  $bararray['maxw'] += $w;
858  ++$k;
859  $w = 0;
860  }
861  }
862  return $bararray;
863  }
864 
874  protected function barcode_i25($code, $checksum=false) {
875  $chr['0'] = '11221';
876  $chr['1'] = '21112';
877  $chr['2'] = '12112';
878  $chr['3'] = '22111';
879  $chr['4'] = '11212';
880  $chr['5'] = '21211';
881  $chr['6'] = '12211';
882  $chr['7'] = '11122';
883  $chr['8'] = '21121';
884  $chr['9'] = '12121';
885  $chr['A'] = '11';
886  $chr['Z'] = '21';
887  if ($checksum) {
888  // add checksum
889  $code .= $this->checksum_s25($code);
890  }
891  if((strlen($code) % 2) != 0) {
892  // add leading zero if code-length is odd
893  $code = '0'.$code;
894  }
895  // add start and stop codes
896  $code = 'AA'.strtolower($code).'ZA';
897 
898  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
899  $k = 0;
900  $clen = strlen($code);
901  for ($i = 0; $i < $clen; $i = ($i + 2)) {
902  $char_bar = $code{$i};
903  $char_space = $code{$i+1};
904  if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
905  // invalid character
906  return false;
907  }
908  // create a bar-space sequence
909  $seq = '';
910  $chrlen = strlen($chr[$char_bar]);
911  for ($s = 0; $s < $chrlen; $s++){
912  $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
913  }
914  $seqlen = strlen($seq);
915  for ($j = 0; $j < $seqlen; ++$j) {
916  if (($j % 2) == 0) {
917  $t = true; // bar
918  } else {
919  $t = false; // space
920  }
921  $w = $seq{$j};
922  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
923  $bararray['maxw'] += $w;
924  ++$k;
925  }
926  }
927  return $bararray;
928  }
929 
938  protected function barcode_c128($code, $type='') {
939  $chr = array(
940  '212222', /* 00 */
941  '222122', /* 01 */
942  '222221', /* 02 */
943  '121223', /* 03 */
944  '121322', /* 04 */
945  '131222', /* 05 */
946  '122213', /* 06 */
947  '122312', /* 07 */
948  '132212', /* 08 */
949  '221213', /* 09 */
950  '221312', /* 10 */
951  '231212', /* 11 */
952  '112232', /* 12 */
953  '122132', /* 13 */
954  '122231', /* 14 */
955  '113222', /* 15 */
956  '123122', /* 16 */
957  '123221', /* 17 */
958  '223211', /* 18 */
959  '221132', /* 19 */
960  '221231', /* 20 */
961  '213212', /* 21 */
962  '223112', /* 22 */
963  '312131', /* 23 */
964  '311222', /* 24 */
965  '321122', /* 25 */
966  '321221', /* 26 */
967  '312212', /* 27 */
968  '322112', /* 28 */
969  '322211', /* 29 */
970  '212123', /* 30 */
971  '212321', /* 31 */
972  '232121', /* 32 */
973  '111323', /* 33 */
974  '131123', /* 34 */
975  '131321', /* 35 */
976  '112313', /* 36 */
977  '132113', /* 37 */
978  '132311', /* 38 */
979  '211313', /* 39 */
980  '231113', /* 40 */
981  '231311', /* 41 */
982  '112133', /* 42 */
983  '112331', /* 43 */
984  '132131', /* 44 */
985  '113123', /* 45 */
986  '113321', /* 46 */
987  '133121', /* 47 */
988  '313121', /* 48 */
989  '211331', /* 49 */
990  '231131', /* 50 */
991  '213113', /* 51 */
992  '213311', /* 52 */
993  '213131', /* 53 */
994  '311123', /* 54 */
995  '311321', /* 55 */
996  '331121', /* 56 */
997  '312113', /* 57 */
998  '312311', /* 58 */
999  '332111', /* 59 */
1000  '314111', /* 60 */
1001  '221411', /* 61 */
1002  '431111', /* 62 */
1003  '111224', /* 63 */
1004  '111422', /* 64 */
1005  '121124', /* 65 */
1006  '121421', /* 66 */
1007  '141122', /* 67 */
1008  '141221', /* 68 */
1009  '112214', /* 69 */
1010  '112412', /* 70 */
1011  '122114', /* 71 */
1012  '122411', /* 72 */
1013  '142112', /* 73 */
1014  '142211', /* 74 */
1015  '241211', /* 75 */
1016  '221114', /* 76 */
1017  '413111', /* 77 */
1018  '241112', /* 78 */
1019  '134111', /* 79 */
1020  '111242', /* 80 */
1021  '121142', /* 81 */
1022  '121241', /* 82 */
1023  '114212', /* 83 */
1024  '124112', /* 84 */
1025  '124211', /* 85 */
1026  '411212', /* 86 */
1027  '421112', /* 87 */
1028  '421211', /* 88 */
1029  '212141', /* 89 */
1030  '214121', /* 90 */
1031  '412121', /* 91 */
1032  '111143', /* 92 */
1033  '111341', /* 93 */
1034  '131141', /* 94 */
1035  '114113', /* 95 */
1036  '114311', /* 96 */
1037  '411113', /* 97 */
1038  '411311', /* 98 */
1039  '113141', /* 99 */
1040  '114131', /* 100 */
1041  '311141', /* 101 */
1042  '411131', /* 102 */
1043  '211412', /* 103 START A */
1044  '211214', /* 104 START B */
1045  '211232', /* 105 START C */
1046  '233111', /* STOP */
1047  '200000' /* END */
1048  );
1049  // ASCII characters for code A (ASCII 00 - 95)
1050  $keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
1051  $keys_a .= chr(0).chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8).chr(9);
1052  $keys_a .= chr(10).chr(11).chr(12).chr(13).chr(14).chr(15).chr(16).chr(17).chr(18).chr(19);
1053  $keys_a .= chr(20).chr(21).chr(22).chr(23).chr(24).chr(25).chr(26).chr(27).chr(28).chr(29);
1054  $keys_a .= chr(30).chr(31);
1055  // ASCII characters for code B (ASCII 32 - 127)
1056  $keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
1057  // special codes
1058  $fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
1059  $fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
1060  // array of symbols
1061  $code_data = array();
1062  // lenght of the code
1063  $len = strlen($code);
1064  switch(strtoupper($type)) {
1065  case 'A': { // MODE A
1066  $startid = 103;
1067  for ($i = 0; $i < $len; ++$i) {
1068  $char = $code{$i};
1069  $char_id = ord($char);
1070  if (($char_id >= 241) AND ($char_id <= 244)) {
1071  $code_data[] = $fnc_a[$char_id];
1072  } elseif (($char_id >= 0) AND ($char_id <= 95)) {
1073  $code_data[] = strpos($keys_a, $char);
1074  } else {
1075  return false;
1076  }
1077  }
1078  break;
1079  }
1080  case 'B': { // MODE B
1081  $startid = 104;
1082  for ($i = 0; $i < $len; ++$i) {
1083  $char = $code{$i};
1084  $char_id = ord($char);
1085  if (($char_id >= 241) AND ($char_id <= 244)) {
1086  $code_data[] = $fnc_b[$char_id];
1087  } elseif (($char_id >= 32) AND ($char_id <= 127)) {
1088  $code_data[] = strpos($keys_b, $char);
1089  } else {
1090  return false;
1091  }
1092  }
1093  break;
1094  }
1095  case 'C': { // MODE C
1096  $startid = 105;
1097  if (ord($code{0}) == 241) {
1098  $code_data[] = 102;
1099  $code = substr($code, 1);
1100  --$len;
1101  }
1102  if (($len % 2) != 0) {
1103  // the length must be even
1104  return false;
1105  }
1106  for ($i = 0; $i < $len; $i+=2) {
1107  $chrnum = $code{$i}.$code{$i+1};
1108  if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
1109  $code_data[] = intval($chrnum);
1110  } else {
1111  return false;
1112  }
1113  }
1114  break;
1115  }
1116  default: { // MODE AUTO
1117  // split code into sequences
1118  $sequence = array();
1119  // get numeric sequences (if any)
1120  $numseq = array();
1121  preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
1122  if (isset($numseq[1]) AND !empty($numseq[1])) {
1123  $end_offset = 0;
1124  foreach ($numseq[1] as $val) {
1125  $offset = $val[1];
1126  if ($offset > $end_offset) {
1127  // non numeric sequence
1128  $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset))));
1129  }
1130  // numeric sequence
1131  $slen = strlen($val[0]);
1132  if (($slen % 2) != 0) {
1133  // the length must be even
1134  --$slen;
1135  }
1136  $sequence[] = array('C', substr($code, $offset, $slen), $slen);
1137  $end_offset = $offset + $slen;
1138  }
1139  if ($end_offset < $len) {
1140  $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
1141  }
1142  } else {
1143  // text code (non C mode)
1144  $sequence = array_merge($sequence, $this->get128ABsequence($code));
1145  }
1146  // process the sequence
1147  foreach ($sequence as $key => $seq) {
1148  switch($seq[0]) {
1149  case 'A': {
1150  if ($key == 0) {
1151  $startid = 103;
1152  } elseif ($sequence[($key - 1)][0] != 'A') {
1153  if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND (!isset($sequence[($key - 1)][3]))) {
1154  // single character shift
1155  $code_data[] = 98;
1156  // mark shift
1157  $sequence[$key][3] = true;
1158  } elseif (!isset($sequence[($key - 1)][3])) {
1159  $code_data[] = 101;
1160  }
1161  }
1162  for ($i = 0; $i < $seq[2]; ++$i) {
1163  $char = $seq[1]{$i};
1164  $char_id = ord($char);
1165  if (($char_id >= 241) AND ($char_id <= 244)) {
1166  $code_data[] = $fnc_a[$char_id];
1167  } else {
1168  $code_data[] = strpos($keys_a, $char);
1169  }
1170  }
1171  break;
1172  }
1173  case 'B': {
1174  if ($key == 0) {
1175  $tmpchr = ord($seq[1]{0});
1176  if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) {
1177  switch ($sequence[($key + 1)][0]) {
1178  case 'A': {
1179  $startid = 103;
1180  $sequence[$key][0] = 'A';
1181  $code_data[] = $fnc_a[$tmpchr];
1182  break;
1183  }
1184  case 'C': {
1185  $startid = 105;
1186  $sequence[$key][0] = 'C';
1187  $code_data[] = $fnc_a[$tmpchr];
1188  break;
1189  }
1190  }
1191  break;
1192  } else {
1193  $startid = 104;
1194  }
1195  } elseif ($sequence[($key - 1)][0] != 'B') {
1196  if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND (!isset($sequence[($key - 1)][3]))) {
1197  // single character shift
1198  $code_data[] = 98;
1199  // mark shift
1200  $sequence[$key][3] = true;
1201  } elseif (!isset($sequence[($key - 1)][3])) {
1202  $code_data[] = 100;
1203  }
1204  }
1205  for ($i = 0; $i < $seq[2]; ++$i) {
1206  $char = $seq[1]{$i};
1207  $char_id = ord($char);
1208  if (($char_id >= 241) AND ($char_id <= 244)) {
1209  $code_data[] = $fnc_b[$char_id];
1210  } else {
1211  $code_data[] = strpos($keys_b, $char);
1212  }
1213  }
1214  break;
1215  }
1216  case 'C': {
1217  if ($key == 0) {
1218  $startid = 105;
1219  } elseif ($sequence[($key - 1)][0] != 'C') {
1220  $code_data[] = 99;
1221  }
1222  for ($i = 0; $i < $seq[2]; $i+=2) {
1223  $chrnum = $seq[1]{$i}.$seq[1]{$i+1};
1224  $code_data[] = intval($chrnum);
1225  }
1226  break;
1227  }
1228  }
1229  }
1230  }
1231  }
1232  // calculate check character
1233  $sum = $startid;
1234  foreach ($code_data as $key => $val) {
1235  $sum += ($val * ($key + 1));
1236  }
1237  // add check character
1238  $code_data[] = ($sum % 103);
1239  // add stop sequence
1240  $code_data[] = 106;
1241  $code_data[] = 107;
1242  // add start code at the beginning
1243  array_unshift($code_data, $startid);
1244  // build barcode array
1245  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1246  foreach ($code_data as $val) {
1247  $seq = $chr[$val];
1248  for ($j = 0; $j < 6; ++$j) {
1249  if (($j % 2) == 0) {
1250  $t = true; // bar
1251  } else {
1252  $t = false; // space
1253  }
1254  $w = $seq{$j};
1255  $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1256  $bararray['maxw'] += $w;
1257  }
1258  }
1259  return $bararray;
1260  }
1261 
1268  protected function get128ABsequence($code) {
1269  $len = strlen($code);
1270  $sequence = array();
1271  // get A sequences (if any)
1272  $numseq = array();
1273  preg_match_all('/([\0-\31])/', $code, $numseq, PREG_OFFSET_CAPTURE);
1274  if (isset($numseq[1]) AND !empty($numseq[1])) {
1275  $end_offset = 0;
1276  foreach ($numseq[1] as $val) {
1277  $offset = $val[1];
1278  if ($offset > $end_offset) {
1279  // B sequence
1280  $sequence[] = array('B', substr($code, $end_offset, ($offset - $end_offset)), ($offset - $end_offset));
1281  }
1282  // A sequence
1283  $slen = strlen($val[0]);
1284  $sequence[] = array('A', substr($code, $offset, $slen), $slen);
1285  $end_offset = $offset + $slen;
1286  }
1287  if ($end_offset < $len) {
1288  $sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset));
1289  }
1290  } else {
1291  // only B sequence
1292  $sequence[] = array('B', $code, $len);
1293  }
1294  return $sequence;
1295  }
1296 
1307  protected function barcode_eanupc($code, $len=13) {
1308  $upce = false;
1309  if ($len == 6) {
1310  $len = 12; // UPC-A
1311  $upce = true; // UPC-E mode
1312  }
1313  $data_len = $len - 1;
1314  //Padding
1315  $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
1316  $code_len = strlen($code);
1317  // calculate check digit
1318  $sum_a = 0;
1319  for ($i = 1; $i < $data_len; $i+=2) {
1320  $sum_a += $code{$i};
1321  }
1322  if ($len > 12) {
1323  $sum_a *= 3;
1324  }
1325  $sum_b = 0;
1326  for ($i = 0; $i < $data_len; $i+=2) {
1327  $sum_b += ($code{$i});
1328  }
1329  if ($len < 13) {
1330  $sum_b *= 3;
1331  }
1332  $r = ($sum_a + $sum_b) % 10;
1333  if($r > 0) {
1334  $r = (10 - $r);
1335  }
1336  if ($code_len == $data_len) {
1337  // add check digit
1338  $code .= $r;
1339  } elseif ($r !== intval($code{$data_len})) {
1340  // wrong checkdigit
1341  return false;
1342  }
1343  if ($len == 12) {
1344  // UPC-A
1345  $code = '0'.$code;
1346  ++$len;
1347  }
1348  if ($upce) {
1349  // convert UPC-A to UPC-E
1350  $tmp = substr($code, 4, 3);
1351  if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
1352  // manufacturer code ends in 000, 100, or 200
1353  $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
1354  } else {
1355  $tmp = substr($code, 5, 2);
1356  if ($tmp == '00') {
1357  // manufacturer code ends in 00
1358  $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
1359  } else {
1360  $tmp = substr($code, 6, 1);
1361  if ($tmp == '0') {
1362  // manufacturer code ends in 0
1363  $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
1364  } else {
1365  // manufacturer code does not end in zero
1366  $upce_code = substr($code, 2, 5).substr($code, 11, 1);
1367  }
1368  }
1369  }
1370  }
1371  //Convert digits to bars
1372  $codes = array(
1373  'A'=>array( // left odd parity
1374  '0'=>'0001101',
1375  '1'=>'0011001',
1376  '2'=>'0010011',
1377  '3'=>'0111101',
1378  '4'=>'0100011',
1379  '5'=>'0110001',
1380  '6'=>'0101111',
1381  '7'=>'0111011',
1382  '8'=>'0110111',
1383  '9'=>'0001011'),
1384  'B'=>array( // left even parity
1385  '0'=>'0100111',
1386  '1'=>'0110011',
1387  '2'=>'0011011',
1388  '3'=>'0100001',
1389  '4'=>'0011101',
1390  '5'=>'0111001',
1391  '6'=>'0000101',
1392  '7'=>'0010001',
1393  '8'=>'0001001',
1394  '9'=>'0010111'),
1395  'C'=>array( // right
1396  '0'=>'1110010',
1397  '1'=>'1100110',
1398  '2'=>'1101100',
1399  '3'=>'1000010',
1400  '4'=>'1011100',
1401  '5'=>'1001110',
1402  '6'=>'1010000',
1403  '7'=>'1000100',
1404  '8'=>'1001000',
1405  '9'=>'1110100')
1406  );
1407  $parities = array(
1408  '0'=>array('A','A','A','A','A','A'),
1409  '1'=>array('A','A','B','A','B','B'),
1410  '2'=>array('A','A','B','B','A','B'),
1411  '3'=>array('A','A','B','B','B','A'),
1412  '4'=>array('A','B','A','A','B','B'),
1413  '5'=>array('A','B','B','A','A','B'),
1414  '6'=>array('A','B','B','B','A','A'),
1415  '7'=>array('A','B','A','B','A','B'),
1416  '8'=>array('A','B','A','B','B','A'),
1417  '9'=>array('A','B','B','A','B','A')
1418  );
1419  $upce_parities = array();
1420  $upce_parities[0] = array(
1421  '0'=>array('B','B','B','A','A','A'),
1422  '1'=>array('B','B','A','B','A','A'),
1423  '2'=>array('B','B','A','A','B','A'),
1424  '3'=>array('B','B','A','A','A','B'),
1425  '4'=>array('B','A','B','B','A','A'),
1426  '5'=>array('B','A','A','B','B','A'),
1427  '6'=>array('B','A','A','A','B','B'),
1428  '7'=>array('B','A','B','A','B','A'),
1429  '8'=>array('B','A','B','A','A','B'),
1430  '9'=>array('B','A','A','B','A','B')
1431  );
1432  $upce_parities[1] = array(
1433  '0'=>array('A','A','A','B','B','B'),
1434  '1'=>array('A','A','B','A','B','B'),
1435  '2'=>array('A','A','B','B','A','B'),
1436  '3'=>array('A','A','B','B','B','A'),
1437  '4'=>array('A','B','A','A','B','B'),
1438  '5'=>array('A','B','B','A','A','B'),
1439  '6'=>array('A','B','B','B','A','A'),
1440  '7'=>array('A','B','A','B','A','B'),
1441  '8'=>array('A','B','A','B','B','A'),
1442  '9'=>array('A','B','B','A','B','A')
1443  );
1444  $k = 0;
1445  $seq = '101'; // left guard bar
1446  if ($upce) {
1447  $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1448  $p = $upce_parities[$code{1}][$r];
1449  for ($i = 0; $i < 6; ++$i) {
1450  $seq .= $codes[$p[$i]][$upce_code{$i}];
1451  }
1452  $seq .= '010101'; // right guard bar
1453  } else {
1454  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1455  $half_len = intval(ceil($len / 2));
1456  if ($len == 8) {
1457  for ($i = 0; $i < $half_len; ++$i) {
1458  $seq .= $codes['A'][$code{$i}];
1459  }
1460  } else {
1461  $p = $parities[$code{0}];
1462  for ($i = 1; $i < $half_len; ++$i) {
1463  $seq .= $codes[$p[$i-1]][$code{$i}];
1464  }
1465  }
1466  $seq .= '01010'; // center guard bar
1467  for ($i = $half_len; $i < $len; ++$i) {
1468  $seq .= $codes['C'][$code{$i}];
1469  }
1470  $seq .= '101'; // right guard bar
1471  }
1472  $clen = strlen($seq);
1473  $w = 0;
1474  for ($i = 0; $i < $clen; ++$i) {
1475  $w += 1;
1476  if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
1477  if ($seq{$i} == '1') {
1478  $t = true; // bar
1479  } else {
1480  $t = false; // space
1481  }
1482  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1483  $bararray['maxw'] += $w;
1484  ++$k;
1485  $w = 0;
1486  }
1487  }
1488  return $bararray;
1489  }
1490 
1500  protected function barcode_eanext($code, $len=5) {
1501  //Padding
1502  $code = str_pad($code, $len, '0', STR_PAD_LEFT);
1503  // calculate check digit
1504  if ($len == 2) {
1505  $r = $code % 4;
1506  } elseif ($len == 5) {
1507  $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3}));
1508  $r %= 10;
1509  } else {
1510  return false;
1511  }
1512  //Convert digits to bars
1513  $codes = array(
1514  'A'=>array( // left odd parity
1515  '0'=>'0001101',
1516  '1'=>'0011001',
1517  '2'=>'0010011',
1518  '3'=>'0111101',
1519  '4'=>'0100011',
1520  '5'=>'0110001',
1521  '6'=>'0101111',
1522  '7'=>'0111011',
1523  '8'=>'0110111',
1524  '9'=>'0001011'),
1525  'B'=>array( // left even parity
1526  '0'=>'0100111',
1527  '1'=>'0110011',
1528  '2'=>'0011011',
1529  '3'=>'0100001',
1530  '4'=>'0011101',
1531  '5'=>'0111001',
1532  '6'=>'0000101',
1533  '7'=>'0010001',
1534  '8'=>'0001001',
1535  '9'=>'0010111')
1536  );
1537  $parities = array();
1538  $parities[2] = array(
1539  '0'=>array('A','A'),
1540  '1'=>array('A','B'),
1541  '2'=>array('B','A'),
1542  '3'=>array('B','B')
1543  );
1544  $parities[5] = array(
1545  '0'=>array('B','B','A','A','A'),
1546  '1'=>array('B','A','B','A','A'),
1547  '2'=>array('B','A','A','B','A'),
1548  '3'=>array('B','A','A','A','B'),
1549  '4'=>array('A','B','B','A','A'),
1550  '5'=>array('A','A','B','B','A'),
1551  '6'=>array('A','A','A','B','B'),
1552  '7'=>array('A','B','A','B','A'),
1553  '8'=>array('A','B','A','A','B'),
1554  '9'=>array('A','A','B','A','B')
1555  );
1556  $p = $parities[$len][$r];
1557  $seq = '1011'; // left guard bar
1558  $seq .= $codes[$p[0]][$code{0}];
1559  for ($i = 1; $i < $len; ++$i) {
1560  $seq .= '01'; // separator
1561  $seq .= $codes[$p[$i]][$code{$i}];
1562  }
1563  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1564  return $this->binseq_to_array($seq, $bararray);
1565  }
1566 
1575  protected function barcode_postnet($code, $planet=false) {
1576  // bar lenght
1577  if ($planet) {
1578  $barlen = Array(
1579  0 => Array(1,1,2,2,2),
1580  1 => Array(2,2,2,1,1),
1581  2 => Array(2,2,1,2,1),
1582  3 => Array(2,2,1,1,2),
1583  4 => Array(2,1,2,2,1),
1584  5 => Array(2,1,2,1,2),
1585  6 => Array(2,1,1,2,2),
1586  7 => Array(1,2,2,2,1),
1587  8 => Array(1,2,2,1,2),
1588  9 => Array(1,2,1,2,2)
1589  );
1590  } else {
1591  $barlen = Array(
1592  0 => Array(2,2,1,1,1),
1593  1 => Array(1,1,1,2,2),
1594  2 => Array(1,1,2,1,2),
1595  3 => Array(1,1,2,2,1),
1596  4 => Array(1,2,1,1,2),
1597  5 => Array(1,2,1,2,1),
1598  6 => Array(1,2,2,1,1),
1599  7 => Array(2,1,1,1,2),
1600  8 => Array(2,1,1,2,1),
1601  9 => Array(2,1,2,1,1)
1602  );
1603  }
1604  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1605  $k = 0;
1606  $code = str_replace('-', '', $code);
1607  $code = str_replace(' ', '', $code);
1608  $len = strlen($code);
1609  // calculate checksum
1610  $sum = 0;
1611  for ($i = 0; $i < $len; ++$i) {
1612  $sum += intval($code{$i});
1613  }
1614  $chkd = ($sum % 10);
1615  if($chkd > 0) {
1616  $chkd = (10 - $chkd);
1617  }
1618  $code .= $chkd;
1619  $len = strlen($code);
1620  // start bar
1621  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1622  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1623  $bararray['maxw'] += 2;
1624  for ($i = 0; $i < $len; ++$i) {
1625  for ($j = 0; $j < 5; ++$j) {
1626  $h = $barlen[$code{$i}][$j];
1627  $p = floor(1 / $h);
1628  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1629  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1630  $bararray['maxw'] += 2;
1631  }
1632  }
1633  // end bar
1634  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1635  $bararray['maxw'] += 1;
1636  return $bararray;
1637  }
1638 
1648  protected function barcode_rms4cc($code, $kix=false) {
1649  $notkix = !$kix;
1650  // bar mode
1651  // 1 = pos 1, length 2
1652  // 2 = pos 1, length 3
1653  // 3 = pos 2, length 1
1654  // 4 = pos 2, length 2
1655  $barmode = array(
1656  '0' => array(3,3,2,2),
1657  '1' => array(3,4,1,2),
1658  '2' => array(3,4,2,1),
1659  '3' => array(4,3,1,2),
1660  '4' => array(4,3,2,1),
1661  '5' => array(4,4,1,1),
1662  '6' => array(3,1,4,2),
1663  '7' => array(3,2,3,2),
1664  '8' => array(3,2,4,1),
1665  '9' => array(4,1,3,2),
1666  'A' => array(4,1,4,1),
1667  'B' => array(4,2,3,1),
1668  'C' => array(3,1,2,4),
1669  'D' => array(3,2,1,4),
1670  'E' => array(3,2,2,3),
1671  'F' => array(4,1,1,4),
1672  'G' => array(4,1,2,3),
1673  'H' => array(4,2,1,3),
1674  'I' => array(1,3,4,2),
1675  'J' => array(1,4,3,2),
1676  'K' => array(1,4,4,1),
1677  'L' => array(2,3,3,2),
1678  'M' => array(2,3,4,1),
1679  'N' => array(2,4,3,1),
1680  'O' => array(1,3,2,4),
1681  'P' => array(1,4,1,4),
1682  'Q' => array(1,4,2,3),
1683  'R' => array(2,3,1,4),
1684  'S' => array(2,3,2,3),
1685  'T' => array(2,4,1,3),
1686  'U' => array(1,1,4,4),
1687  'V' => array(1,2,3,4),
1688  'W' => array(1,2,4,3),
1689  'X' => array(2,1,3,4),
1690  'Y' => array(2,1,4,3),
1691  'Z' => array(2,2,3,3)
1692  );
1693  $code = strtoupper($code);
1694  $len = strlen($code);
1695  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
1696  if ($notkix) {
1697  // table for checksum calculation (row,col)
1698  $checktable = array(
1699  '0' => array(1,1),
1700  '1' => array(1,2),
1701  '2' => array(1,3),
1702  '3' => array(1,4),
1703  '4' => array(1,5),
1704  '5' => array(1,0),
1705  '6' => array(2,1),
1706  '7' => array(2,2),
1707  '8' => array(2,3),
1708  '9' => array(2,4),
1709  'A' => array(2,5),
1710  'B' => array(2,0),
1711  'C' => array(3,1),
1712  'D' => array(3,2),
1713  'E' => array(3,3),
1714  'F' => array(3,4),
1715  'G' => array(3,5),
1716  'H' => array(3,0),
1717  'I' => array(4,1),
1718  'J' => array(4,2),
1719  'K' => array(4,3),
1720  'L' => array(4,4),
1721  'M' => array(4,5),
1722  'N' => array(4,0),
1723  'O' => array(5,1),
1724  'P' => array(5,2),
1725  'Q' => array(5,3),
1726  'R' => array(5,4),
1727  'S' => array(5,5),
1728  'T' => array(5,0),
1729  'U' => array(0,1),
1730  'V' => array(0,2),
1731  'W' => array(0,3),
1732  'X' => array(0,4),
1733  'Y' => array(0,5),
1734  'Z' => array(0,0)
1735  );
1736  $row = 0;
1737  $col = 0;
1738  for ($i = 0; $i < $len; ++$i) {
1739  $row += $checktable[$code{$i}][0];
1740  $col += $checktable[$code{$i}][1];
1741  }
1742  $row %= 6;
1743  $col %= 6;
1744  $chk = array_keys($checktable, array($row,$col));
1745  $code .= $chk[0];
1746  ++$len;
1747  }
1748  $k = 0;
1749  if ($notkix) {
1750  // start bar
1751  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1752  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1753  $bararray['maxw'] += 2;
1754  }
1755  for ($i = 0; $i < $len; ++$i) {
1756  for ($j = 0; $j < 4; ++$j) {
1757  switch ($barmode[$code{$i}][$j]) {
1758  case 1: {
1759  $p = 0;
1760  $h = 2;
1761  break;
1762  }
1763  case 2: {
1764  $p = 0;
1765  $h = 3;
1766  break;
1767  }
1768  case 3: {
1769  $p = 1;
1770  $h = 1;
1771  break;
1772  }
1773  case 4: {
1774  $p = 1;
1775  $h = 2;
1776  break;
1777  }
1778  }
1779  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1780  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1781  $bararray['maxw'] += 2;
1782  }
1783  }
1784  if ($notkix) {
1785  // stop bar
1786  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
1787  $bararray['maxw'] += 1;
1788  }
1789  return $bararray;
1790  }
1791 
1799  protected function barcode_codabar($code) {
1800  $chr = array(
1801  '0' => '11111221',
1802  '1' => '11112211',
1803  '2' => '11121121',
1804  '3' => '22111111',
1805  '4' => '11211211',
1806  '5' => '21111211',
1807  '6' => '12111121',
1808  '7' => '12112111',
1809  '8' => '12211111',
1810  '9' => '21121111',
1811  '-' => '11122111',
1812  '$' => '11221111',
1813  ':' => '21112121',
1814  '/' => '21211121',
1815  '.' => '21212111',
1816  '+' => '11222221',
1817  'A' => '11221211',
1818  'B' => '12121121',
1819  'C' => '11121221',
1820  'D' => '11122211'
1821  );
1822  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1823  $k = 0;
1824  $w = 0;
1825  $seq = '';
1826  $code = 'A'.strtoupper($code).'A';
1827  $len = strlen($code);
1828  for ($i = 0; $i < $len; ++$i) {
1829  if (!isset($chr[$code{$i}])) {
1830  return false;
1831  }
1832  $seq = $chr[$code{$i}];
1833  for ($j = 0; $j < 8; ++$j) {
1834  if (($j % 2) == 0) {
1835  $t = true; // bar
1836  } else {
1837  $t = false; // space
1838  }
1839  $w = $seq{$j};
1840  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1841  $bararray['maxw'] += $w;
1842  ++$k;
1843  }
1844  }
1845  return $bararray;
1846  }
1847 
1855  protected function barcode_code11($code) {
1856  $chr = array(
1857  '0' => '111121',
1858  '1' => '211121',
1859  '2' => '121121',
1860  '3' => '221111',
1861  '4' => '112121',
1862  '5' => '212111',
1863  '6' => '122111',
1864  '7' => '111221',
1865  '8' => '211211',
1866  '9' => '211111',
1867  '-' => '112111',
1868  'S' => '112211'
1869  );
1870  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1871  $k = 0;
1872  $w = 0;
1873  $seq = '';
1874  $len = strlen($code);
1875  // calculate check digit C
1876  $p = 1;
1877  $check = 0;
1878  for ($i = ($len - 1); $i >= 0; --$i) {
1879  $digit = $code{$i};
1880  if ($digit == '-') {
1881  $dval = 10;
1882  } else {
1883  $dval = intval($digit);
1884  }
1885  $check += ($dval * $p);
1886  ++$p;
1887  if ($p > 10) {
1888  $p = 1;
1889  }
1890  }
1891  $check %= 11;
1892  if ($check == 10) {
1893  $check = '-';
1894  }
1895  $code .= $check;
1896  if ($len > 10) {
1897  // calculate check digit K
1898  $p = 1;
1899  $check = 0;
1900  for ($i = $len; $i >= 0; --$i) {
1901  $digit = $code{$i};
1902  if ($digit == '-') {
1903  $dval = 10;
1904  } else {
1905  $dval = intval($digit);
1906  }
1907  $check += ($dval * $p);
1908  ++$p;
1909  if ($p > 9) {
1910  $p = 1;
1911  }
1912  }
1913  $check %= 11;
1914  $code .= $check;
1915  ++$len;
1916  }
1917  $code = 'S'.$code.'S';
1918  $len += 3;
1919  for ($i = 0; $i < $len; ++$i) {
1920  if (!isset($chr[$code{$i}])) {
1921  return false;
1922  }
1923  $seq = $chr[$code{$i}];
1924  for ($j = 0; $j < 6; ++$j) {
1925  if (($j % 2) == 0) {
1926  $t = true; // bar
1927  } else {
1928  $t = false; // space
1929  }
1930  $w = $seq{$j};
1931  $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1932  $bararray['maxw'] += $w;
1933  ++$k;
1934  }
1935  }
1936  return $bararray;
1937  }
1938 
1946  protected function barcode_pharmacode($code) {
1947  $seq = '';
1948  $code = intval($code);
1949  while ($code > 0) {
1950  if (($code % 2) == 0) {
1951  $seq .= '11100';
1952  $code -= 2;
1953  } else {
1954  $seq .= '100';
1955  $code -= 1;
1956  }
1957  $code /= 2;
1958  }
1959  $seq = substr($seq, 0, -2);
1960  $seq = strrev($seq);
1961  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1962  return $this->binseq_to_array($seq, $bararray);
1963  }
1964 
1972  protected function barcode_pharmacode2t($code) {
1973  $seq = '';
1974  $code = intval($code);
1975  do {
1976  switch ($code % 3) {
1977  case 0: {
1978  $seq .= '3';
1979  $code = ($code - 3) / 3;
1980  break;
1981  }
1982  case 1: {
1983  $seq .= '1';
1984  $code = ($code - 1) / 3;
1985  break;
1986  }
1987  case 2: {
1988  $seq .= '2';
1989  $code = ($code - 2) / 3;
1990  break;
1991  }
1992  }
1993  } while($code != 0);
1994  $seq = strrev($seq);
1995  $k = 0;
1996  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1997  $len = strlen($seq);
1998  for ($i = 0; $i < $len; ++$i) {
1999  switch ($seq{$i}) {
2000  case '1': {
2001  $p = 1;
2002  $h = 1;
2003  break;
2004  }
2005  case '2': {
2006  $p = 0;
2007  $h = 1;
2008  break;
2009  }
2010  case '3': {
2011  $p = 0;
2012  $h = 2;
2013  break;
2014  }
2015  }
2016  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
2017  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
2018  $bararray['maxw'] += 2;
2019  }
2020  unset($bararray['bcode'][($k - 1)]);
2021  --$bararray['maxw'];
2022  return $bararray;
2023  }
2024 
2025 
2035  protected function barcode_imb($code) {
2036  $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);
2037  $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);
2038  $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);
2039  $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);
2040  $code_arr = explode('-', $code);
2041  $tracking_number = $code_arr[0];
2042  if (isset($code_arr[1])) {
2043  $routing_code = $code_arr[1];
2044  } else {
2045  $routing_code = '';
2046  }
2047  // Conversion of Routing Code
2048  switch (strlen($routing_code)) {
2049  case 0: {
2050  $binary_code = 0;
2051  break;
2052  }
2053  case 5: {
2054  $binary_code = bcadd($routing_code, '1');
2055  break;
2056  }
2057  case 9: {
2058  $binary_code = bcadd($routing_code, '100001');
2059  break;
2060  }
2061  case 11: {
2062  $binary_code = bcadd($routing_code, '1000100001');
2063  break;
2064  }
2065  default: {
2066  return false;
2067  break;
2068  }
2069  }
2070  $binary_code = bcmul($binary_code, 10);
2071  $binary_code = bcadd($binary_code, $tracking_number{0});
2072  $binary_code = bcmul($binary_code, 5);
2073  $binary_code = bcadd($binary_code, $tracking_number{1});
2074  $binary_code .= substr($tracking_number, 2, 18);
2075  // convert to hexadecimal
2076  $binary_code = $this->dec_to_hex($binary_code);
2077  // pad to get 13 bytes
2078  $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
2079  // convert string to array of bytes
2080  $binary_code_arr = chunk_split($binary_code, 2, "\r");
2081  $binary_code_arr = substr($binary_code_arr, 0, -1);
2082  $binary_code_arr = explode("\r", $binary_code_arr);
2083  // calculate frame check sequence
2084  $fcs = $this->imb_crc11fcs($binary_code_arr);
2085  // exclude first 2 bits from first byte
2086  $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
2087  $binary_code_102bit = $first_byte.substr($binary_code, 2);
2088  // convert binary data to codewords
2089  $codewords = array();
2090  $data = $this->hex_to_dec($binary_code_102bit);
2091  $codewords[0] = bcmod($data, 636) * 2;
2092  $data = bcdiv($data, 636);
2093  for ($i = 1; $i < 9; ++$i) {
2094  $codewords[$i] = bcmod($data, 1365);
2095  $data = bcdiv($data, 1365);
2096  }
2097  $codewords[9] = $data;
2098  if (($fcs >> 10) == 1) {
2099  $codewords[9] += 659;
2100  }
2101  // generate lookup tables
2102  $table2of13 = $this->imb_tables(2, 78);
2103  $table5of13 = $this->imb_tables(5, 1287);
2104  // convert codewords to characters
2105  $characters = array();
2106  $bitmask = 512;
2107  foreach($codewords as $k => $val) {
2108  if ($val <= 1286) {
2109  $chrcode = $table5of13[$val];
2110  } else {
2111  $chrcode = $table2of13[($val - 1287)];
2112  }
2113  if (($fcs & $bitmask) > 0) {
2114  // bitwise invert
2115  $chrcode = ((~$chrcode) & 8191);
2116  }
2117  $characters[] = $chrcode;
2118  $bitmask /= 2;
2119  }
2120  $characters = array_reverse($characters);
2121  // build bars
2122  $k = 0;
2123  $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
2124  for ($i = 0; $i < 65; ++$i) {
2125  $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
2126  $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
2127  if ($asc AND $dsc) {
2128  // full bar (F)
2129  $p = 0;
2130  $h = 3;
2131  } elseif ($asc) {
2132  // ascender (A)
2133  $p = 0;
2134  $h = 2;
2135  } elseif ($dsc) {
2136  // descender (D)
2137  $p = 1;
2138  $h = 2;
2139  } else {
2140  // tracker (T)
2141  $p = 1;
2142  $h = 1;
2143  }
2144  $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
2145  $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
2146  $bararray['maxw'] += 2;
2147  }
2148  unset($bararray['bcode'][($k - 1)]);
2149  --$bararray['maxw'];
2150  return $bararray;
2151  }
2152 
2159  public function dec_to_hex($number) {
2160  $i = 0;
2161  $hex = array();
2162  if($number == 0) {
2163  return '00';
2164  }
2165  while($number > 0) {
2166  if($number == 0) {
2167  array_push($hex, '0');
2168  } else {
2169  array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
2170  $number = bcdiv($number, '16', 0);
2171  }
2172  }
2173  $hex = array_reverse($hex);
2174  return implode($hex);
2175  }
2176 
2183  public function hex_to_dec($hex) {
2184  $dec = 0;
2185  $bitval = 1;
2186  $len = strlen($hex);
2187  for($pos = ($len - 1); $pos >= 0; --$pos) {
2188  $dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval));
2189  $bitval = bcmul($bitval, 16);
2190  }
2191  return $dec;
2192  }
2193 
2200  protected function imb_crc11fcs($code_arr) {
2201  $genpoly = 0x0F35; // generator polynomial
2202  $fcs = 0x07FF; // Frame Check Sequence
2203  // do most significant byte skipping the 2 most significant bits
2204  $data = hexdec($code_arr[0]) << 5;
2205  for ($bit = 2; $bit < 8; ++$bit) {
2206  if (($fcs ^ $data) & 0x400) {
2207  $fcs = ($fcs << 1) ^ $genpoly;
2208  } else {
2209  $fcs = ($fcs << 1);
2210  }
2211  $fcs &= 0x7FF;
2212  $data <<= 1;
2213  }
2214  // do rest of bytes
2215  for ($byte = 1; $byte < 13; ++$byte) {
2216  $data = hexdec($code_arr[$byte]) << 3;
2217  for ($bit = 0; $bit < 8; ++$bit) {
2218  if (($fcs ^ $data) & 0x400) {
2219  $fcs = ($fcs << 1) ^ $genpoly;
2220  } else {
2221  $fcs = ($fcs << 1);
2222  }
2223  $fcs &= 0x7FF;
2224  $data <<= 1;
2225  }
2226  }
2227  return $fcs;
2228  }
2229 
2236  protected function imb_reverse_us($num) {
2237  $rev = 0;
2238  for ($i = 0; $i < 16; ++$i) {
2239  $rev <<= 1;
2240  $rev |= ($num & 1);
2241  $num >>= 1;
2242  }
2243  return $rev;
2244  }
2245 
2253  protected function imb_tables($n, $size) {
2254  $table = array();
2255  $lli = 0; // LUT lower index
2256  $lui = $size - 1; // LUT upper index
2257  for ($count = 0; $count < 8192; ++$count) {
2258  $bit_count = 0;
2259  for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
2260  $bit_count += intval(($count & (1 << $bit_index)) != 0);
2261  }
2262  // if we don't have the right number of bits on, go on to the next value
2263  if ($bit_count == $n) {
2264  $reverse = ($this->imb_reverse_us($count) >> 3);
2265  // if the reverse is less than count, we have already visited this pair before
2266  if ($reverse >= $count) {
2267  // If count is symmetric, place it at the first free slot from the end of the list.
2268  // 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
2269  if ($reverse == $count) {
2270  $table[$lui] = $count;
2271  --$lui;
2272  } else {
2273  $table[$lli] = $count;
2274  ++$lli;
2275  $table[$lli] = $reverse;
2276  ++$lli;
2277  }
2278  }
2279  }
2280  }
2281  return $table;
2282  }
2283 
2284 } // end of class
2285 //============================================================+
2286 // END OF FILE
2287 //============================================================+




Korrekturen, Hinweise und Ergänzungen

Bitte scheuen Sie sich nicht und melden Sie, was auf dieser Seite sachlich falsch oder irreführend ist, was ergänzt werden sollte, was fehlt usw. Dazu bitte oben aus dem Menü Seite den Eintrag Support Forum wählen. Es ist eine kostenlose Anmeldung erforderlich, um Anmerkungen zu posten. Unpassende Postings, Spam usw. werden kommentarlos entfernt.