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