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