some portal work
[openemr.git] / library / classes / php-barcode.php
blob921d5f0b5885a49b36f133fec3414f8ee4362e50
1 <?php
2 /*
3 * BarCode Coder Library (BCC Library)
4 * BCCL Version 2.0
6 * Porting : PHP
7 * Version : 2.0.3
9 * Date : 2013-01-06
10 * Author : DEMONTE Jean-Baptiste <jbdemonte@gmail.com>
11 * HOUREZ Jonathan
13 * Web site: https://barcode-coder.com/
14 * dual licence : https://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
15 * https://www.gnu.org/licenses/gpl.html
16 * BarCode Coder Library
17 * @package BCC Library
18 * @author DEMONTE Jean-Baptiste <jbdemonte@gmail.com>
19 * @author HOUREZ Jonathan
20 * @copyright 2013
22 * Added to Openemr by Terry Hill terry@lillysystems.com
23 * this is from the barcode-coder website
28 class Barcode
31 public static function gd($res, $color, $x, $y, $angle, $type, $datas, $width = null, $height = null)
33 return self::_draw(__FUNCTION__, $res, $color, $x, $y, $angle, $type, $datas, $width, $height);
36 public static function fpdf($res, $color, $x, $y, $angle, $type, $datas, $width = null, $height = null)
38 return self::_draw(__FUNCTION__, $res, $color, $x, $y, $angle, $type, $datas, $width, $height);
41 private static function _draw($call, $res, $color, $x, $y, $angle, $type, $datas, $width, $height)
43 $digit = '';
44 $hri = '';
45 $code = '';
46 $crc = true;
47 $rect = false;
48 $b2d = false;
50 if (is_array($datas)) {
51 foreach (array('code' => '', 'crc' => true, 'rect' => false) as $v => $def) {
52 $$v = isset($datas[$v]) ? $datas[$v] : $def;
55 $code = $code;
56 } else {
57 $code = $datas;
60 if ($code == '') {
61 return false;
64 $code = (string) $code;
66 $type = strtolower($type);
68 switch ($type) {
69 case 'std25':
70 case 'int25':
71 $digit = BarcodeI25::getDigit($code, $crc, $type);
72 $hri = BarcodeI25::compute($code, $crc, $type);
73 break;
74 case 'ean8':
75 case 'ean13':
76 $digit = BarcodeEAN::getDigit($code, $type);
77 $hri = BarcodeEAN::compute($code, $type);
78 break;
79 case 'upc':
80 $digit = BarcodeUPC::getDigit($code);
81 $hri = BarcodeUPC::compute($code);
82 break;
83 case 'code11':
84 $digit = Barcode11::getDigit($code);
85 $hri = $code;
86 break;
87 case 'code39':
88 $digit = Barcode39::getDigit($code);
89 $hri = $code;
90 break;
91 case 'code93':
92 $digit = Barcode93::getDigit($code, $crc);
93 $hri = $code;
94 break;
95 case 'code128':
96 $digit = Barcode128::getDigit($code);
97 $hri = $code;
98 break;
99 case 'codabar':
100 $digit = BarcodeCodabar::getDigit($code);
101 $hri = $code;
102 break;
103 case 'msi':
104 $digit = BarcodeMSI::getDigit($code, $crc);
105 $hri = BarcodeMSI::compute($code, $crc);
106 break;
107 case 'datamatrix':
108 $digit = BarcodeDatamatrix::getDigit($code, $rect);
109 $hri = $code;
110 $b2d = true;
111 break;
114 if ($digit == '') {
115 return false;
118 if ($b2d) {
119 $width = is_null($width) ? 5 : $width;
120 $height = $width;
121 } else {
122 $width = is_null($width) ? 1 : $width;
123 $height = is_null($height) ? 50 : $height;
124 $digit = self::bitStringTo2DArray($digit);
127 if ($call == 'gd') {
128 $result = self::digitToGDRenderer($res, $color, $x, $y, $angle, $width, $height, $digit);
129 } else if ($call == 'fpdf') {
130 $result = self::digitToFPDFRenderer($res, $color, $x, $y, $angle, $width, $height, $digit);
133 $result['hri'] = $hri;
134 return $result;
137 // convert a bit string to an array of array of bit char
138 private static function bitStringTo2DArray($digit)
140 $d = array();
141 $len = strlen($digit);
142 for ($i=0; $i<$len; $i++) {
143 $d[$i] = $digit[$i];
146 return(array($d));
149 private static function digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit)
151 $lines = count($digit);
152 $columns = count($digit[0]);
153 $angle = deg2rad(-$angle);
154 $cos = cos($angle);
155 $sin = sin($angle);
157 self::_rotate($columns * $mw / 2, $lines * $mh / 2, $cos, $sin, $x, $y);
158 $xi -=$x;
159 $yi -=$y;
160 for ($y=0; $y<$lines; $y++) {
161 $x = -1;
162 while ($x <$columns) {
163 $x++;
164 if ($digit[$y][$x] == '1') {
165 $z = $x;
166 while (($z + 1 <$columns) && ($digit[$y][$z + 1] == '1')) {
167 $z++;
170 $x1 = $x * $mw;
171 $y1 = $y * $mh;
172 $x2 = ($z + 1) * $mw;
173 $y2 = ($y + 1) * $mh;
174 self::_rotate($x1, $y1, $cos, $sin, $xA, $yA);
175 self::_rotate($x2, $y1, $cos, $sin, $xB, $yB);
176 self::_rotate($x2, $y2, $cos, $sin, $xC, $yC);
177 self::_rotate($x1, $y2, $cos, $sin, $xD, $yD);
178 $fn(array(
179 $xA + $xi, $yA + $yi,
180 $xB + $xi, $yB + $yi,
181 $xC + $xi, $yC + $yi,
182 $xD + $xi, $yD + $yi
184 $x = $z + 1;
189 return self::result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin);
192 // GD barcode renderer
193 private static function digitToGDRenderer($gd, $color, $xi, $yi, $angle, $mw, $mh, $digit)
195 $fn = function ($points) use ($gd, $color) {
196 imagefilledpolygon($gd, $points, 4, $color);
198 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
200 // FPDF barcode renderer
201 private static function digitToFPDFRenderer($pdf, $color, $xi, $yi, $angle, $mw, $mh, $digit)
203 if (!is_array($color)) {
204 if (preg_match('`([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})`i', $color, $m)) {
205 $color = array(hexdec($m[1]),hexdec($m[2]),hexdec($m[3]));
206 } else {
207 $color = array(0,0,0);
211 $color = array_values($color);
212 $pdf->SetDrawColor($color[0], $color[1], $color[2]);
213 $pdf->SetFillColor($color[0], $color[1], $color[2]);
215 $fn = function ($points) use ($pdf) {
216 $op = 'f';
217 $h = $pdf->h;
218 $k = $pdf->k;
219 $points_string = '';
220 for ($i=0; $i < 8; $i+=2) {
221 $points_string .= sprintf('%.2F %.2F', $points[$i]*$k, ($h-$points[$i+1])*$k);
222 $points_string .= $i ? ' l ' : ' m ';
225 $pdf->_out($points_string . $op);
227 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
230 private static function result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin)
232 self::_rotate(0, 0, $cos, $sin, $x1, $y1);
233 self::_rotate($columns * $mw, 0, $cos, $sin, $x2, $y2);
234 self::_rotate($columns * $mw, $lines * $mh, $cos, $sin, $x3, $y3);
235 self::_rotate(0, $lines * $mh, $cos, $sin, $x4, $y4);
237 return array(
238 'width' => $columns * $mw,
239 'height'=> $lines * $mh,
240 'p1' => array(
241 'x' => $xi + $x1,
242 'y' => $yi + $y1
244 'p2' => array(
245 'x' => $xi + $x2,
246 'y' => $yi + $y2
248 'p3' => array(
249 'x' => $xi + $x3,
250 'y' => $yi + $y3
252 'p4' => array(
253 'x' => $xi + $x4,
254 'y' => $yi + $y4
259 private static function _rotate($x1, $y1, $cos, $sin, &$x, &$y)
261 $x = $x1 * $cos - $y1 * $sin;
262 $y = $x1 * $sin + $y1 * $cos;
265 public static function rotate($x1, $y1, $angle, &$x, &$y)
267 $angle = deg2rad(-$angle);
268 $cos = cos($angle);
269 $sin = sin($angle);
270 $x = $x1 * $cos - $y1 * $sin;
271 $y = $x1 * $sin + $y1 * $cos;
275 class BarcodeI25
277 static private $encoding = array('NNWWN', 'WNNNW', 'NWNNW', 'WWNNN', 'NNWNW', 'WNWNN', 'NWWNN', 'NNNWW', 'WNNWN','NWNWN');
279 public static function compute($code, $crc, $type)
281 if (! $crc) {
282 if (strlen($code) % 2) {
283 $code = '0' . $code;
285 } else {
286 if (($type == 'int25') && (strlen($code) % 2 == 0)) {
287 $code = '0' . $code;
290 $odd = true;
291 $sum = 0;
292 for ($i=strlen($code)-1; $i>-1; $i--) {
293 $v = intval($code[$i]);
294 $sum += $odd ? 3 * $v : $v;
295 $odd = ! $odd;
298 $code .= (string) ((10 - $sum % 10) % 10);
301 return($code);
304 public static function getDigit($code, $crc, $type)
306 $code = self::compute($code, $crc, $type);
307 if ($code == '') {
308 return($code);
311 $result = '';
313 if ($type == 'int25') { // Interleaved 2 of 5
314 // start
315 $result .= '1010';
317 // digits + CRC
318 $end = strlen($code) / 2;
319 for ($i=0; $i<$end; $i++) {
320 $c1 = $code[2*$i];
321 $c2 = $code[2*$i+1];
322 for ($j=0; $j<5; $j++) {
323 $result .= '1';
324 if (self::$encoding[$c1][$j] == 'W') {
325 $result .= '1';
328 $result .= '0';
329 if (self::$encoding[$c2][$j] == 'W') {
330 $result .= '0';
335 // stop
336 $result .= '1101';
337 } else if ($type == 'std25') {
338 // Standard 2 of 5 is a numeric-only barcode that has been in use a long time.
339 // Unlike Interleaved 2 of 5, all of the information is encoded in the bars; the spaces are fixed width and are used only to separate the bars.
340 // The code is self-checking and does not include a checksum.
342 // start
343 $result .= '11011010';
345 // digits + CRC
346 $end = strlen($code);
347 for ($i=0; $i<$end; $i++) {
348 $c = $code[$i];
349 for ($j=0; $j<5; $j++) {
350 $result .= '1';
351 if (self::$encoding[$c][$j] == 'W') {
352 $result .= '11';
355 $result .= '0';
359 // stop
360 $result .= '11010110';
363 return($result);
368 class BarcodeEAN
370 static private $encoding = array(
371 array('0001101', '0100111', '1110010'),
372 array('0011001', '0110011', '1100110'),
373 array('0010011', '0011011', '1101100'),
374 array('0111101', '0100001', '1000010'),
375 array('0100011', '0011101', '1011100'),
376 array('0110001', '0111001', '1001110'),
377 array('0101111', '0000101', '1010000'),
378 array('0111011', '0010001', '1000100'),
379 array('0110111', '0001001', '1001000'),
380 array('0001011', '0010111', '1110100')
383 static private $first = array('000000','001011','001101','001110','010011','011001','011100','010101','010110','011010');
385 public static function getDigit($code, $type)
387 // Check len (12 for ean13, 7 for ean8)
388 $len = $type == 'ean8' ? 7 : 12;
389 $code = substr($code, 0, $len);
390 if (!preg_match('`[0-9]{'.$len.'}`', $code)) {
391 return('');
394 // get checksum
395 $code = self::compute($code, $type);
397 // process analyse
398 $result = '101'; // start
400 if ($type == 'ean8') {
401 // process left part
402 for ($i=0; $i<4; $i++) {
403 $result .= self::$encoding[intval($code[$i])][0];
406 // center guard bars
407 $result .= '01010';
409 // process right part
410 for ($i=4; $i<8; $i++) {
411 $result .= self::$encoding[intval($code[$i])][2];
413 } else { // ean13
414 // extract first digit and get sequence
415 $seq = self::$first[ intval($code[0]) ];
417 // process left part
418 for ($i=1; $i<7; $i++) {
419 $result .= self::$encoding[intval($code[$i])][ intval($seq[$i-1]) ];
422 // center guard bars
423 $result .= '01010';
425 // process right part
426 for ($i=7; $i<13; $i++) {
427 $result .= self::$encoding[intval($code[$i])][ 2 ];
429 } // ean13
431 $result .= '101'; // stop
432 return($result);
435 public static function compute($code, $type)
437 $len = $type == 'ean13' ? 12 : 7;
438 $code = substr($code, 0, $len);
439 if (!preg_match('`[0-9]{'.$len.'}`', $code)) {
440 return('');
443 $sum = 0;
444 $odd = true;
445 for ($i=$len-1; $i>-1; $i--) {
446 $sum += ($odd ? 3 : 1) * intval($code[$i]);
447 $odd = ! $odd;
450 return($code . ( (string) ((10 - $sum % 10) % 10)));
454 class BarcodeUPC
457 public static function getDigit($code)
459 if (strlen($code) < 12) {
460 $code = '0' . $code;
463 return BarcodeEAN::getDigit($code, 'ean13');
466 public static function compute($code)
468 if (strlen($code) < 12) {
469 $code = '0' . $code;
472 return substr(BarcodeEAN::compute($code, 'ean13'), 1);
476 class BarcodeMSI
478 static private $encoding = array(
479 '100100100100', '100100100110', '100100110100', '100100110110',
480 '100110100100', '100110100110', '100110110100', '100110110110',
481 '110100100100', '110100100110');
483 public static function compute($code, $crc)
485 if (is_array($crc)) {
486 if ($crc['crc1'] == 'mod10') {
487 $code = self::computeMod10($code);
488 } else if ($crc['crc1'] == 'mod11') {
489 $code = self::computeMod11($code);
492 if ($crc['crc2'] == 'mod10') {
493 $code = self::computeMod10($code);
494 } else if ($crc['crc2'] == 'mod11') {
495 $code = self::computeMod11($code);
497 } else if ($crc) {
498 $code = self::computeMod10($code);
501 return($code);
504 private static function computeMod10($code)
506 $len = strlen($code);
507 $toPart1 = $len % 2;
508 $n1 = 0;
509 $sum = 0;
510 for ($i=0; $i<$len; $i++) {
511 if ($toPart1) {
512 $n1 = 10 * $n1 + intval($code[$i]);
513 } else {
514 $sum += intval($code[$i]);
517 $toPart1 = ! $toPart1;
520 $s1 = (string) (2 * $n1);
521 $len = strlen($s1);
522 for ($i=0; $i<$len; $i++) {
523 $sum += intval($s1[$i]);
526 return($code . ( (string) (10 - $sum % 10) % 10));
529 private static function computeMod11($code)
531 $sum = 0;
532 $weight = 2;
533 for ($i=strlen($code)-1; $i>-1; $i--) {
534 $sum += $weight * intval($code[$i]);
535 $weight = $weight == 7 ? 2 : $weight + 1;
538 return($code . ( (string) (11 - $sum % 11) % 11) );
541 public static function getDigit($code, $crc)
543 if (preg_match('`[^0-9]`', $code)) {
544 return '';
547 $index = 0;
548 $result = '';
550 $code = self::compute($code, false);
552 // start
553 $result = '110';
555 // digits
556 $len = strlen($code);
557 for ($i=0; $i<$len; $i++) {
558 $result .= self::$encoding[ intval($code[$i]) ];
561 // stop
562 $result .= '1001';
564 return($result);
568 class Barcode11
570 static private $encoding = array(
571 '101011', '1101011', '1001011', '1100101',
572 '1011011', '1101101', '1001101', '1010011',
573 '1101001', '110101', '101101');
575 public static function getDigit($code)
577 if (preg_match('`[^0-9\-]`', $code)) {
578 return '';
581 $result = '';
582 $intercharacter = '0';
584 // start
585 $result = '1011001' . $intercharacter;
587 // digits
588 $len = strlen($code);
589 for ($i=0; $i<$len; $i++) {
590 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
591 $result .= self::$encoding[ $index ] . $intercharacter;
594 // checksum
595 $weightC = 0;
596 $weightSumC = 0;
597 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
598 $weightSumK = 0;
599 for ($i=$len-1; $i>-1; $i--) {
600 $weightC = $weightC == 10 ? 1 : $weightC + 1;
601 $weightK = $weightK == 10 ? 1 : $weightK + 1;
603 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
605 $weightSumC += $weightC * $index;
606 $weightSumK += $weightK * $index;
609 $c = $weightSumC % 11;
610 $weightSumK += $c;
611 $k = $weightSumK % 11;
613 $result .= self::$encoding[$c] . $intercharacter;
615 if ($len >= 10) {
616 $result .= self::$encoding[$k] . $intercharacter;
619 // stop
620 $result .= '1011001';
622 return($result);
626 class Barcode39
628 static private $encoding = array(
629 '101001101101', '110100101011', '101100101011', '110110010101',
630 '101001101011', '110100110101', '101100110101', '101001011011',
631 '110100101101', '101100101101', '110101001011', '101101001011',
632 '110110100101', '101011001011', '110101100101', '101101100101',
633 '101010011011', '110101001101', '101101001101', '101011001101',
634 '110101010011', '101101010011', '110110101001', '101011010011',
635 '110101101001', '101101101001', '101010110011', '110101011001',
636 '101101011001', '101011011001', '110010101011', '100110101011',
637 '110011010101', '100101101011', '110010110101', '100110110101',
638 '100101011011', '110010101101', '100110101101', '100100100101',
639 '100100101001', '100101001001', '101001001001', '100101101101');
640 public static function getDigit($code)
642 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*';
643 $result = '';
644 $intercharacter = '0';
646 if (strpos($code, '*') !== false) {
647 return('');
650 // Add Start and Stop charactere : *
651 $code = strtoupper('*' . $code . '*');
653 $len = strlen($code);
654 for ($i=0; $i<$len; $i++) {
655 $index = strpos($table, $code[$i]);
656 if ($index === false) {
657 return('');
660 if ($i > 0) {
661 $result .= $intercharacter;
664 $result .= self::$encoding[ $index ];
667 return($result);
671 class Barcode93
673 static private $encoding = array(
674 '100010100', '101001000', '101000100', '101000010',
675 '100101000', '100100100', '100100010', '101010000',
676 '100010010', '100001010', '110101000', '110100100',
677 '110100010', '110010100', '110010010', '110001010',
678 '101101000', '101100100', '101100010', '100110100',
679 '100011010', '101011000', '101001100', '101000110',
680 '100101100', '100010110', '110110100', '110110010',
681 '110101100', '110100110', '110010110', '110011010',
682 '101101100', '101100110', '100110110', '100111010',
683 '100101110', '111010100', '111010010', '111001010',
684 '101101110', '101110110', '110101110', '100100110',
685 '111011010', '111010110', '100110010', '101011110');
687 public static function getDigit($code, $crc)
689 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%____*'; // _ => ($), (%), (/) et (+)
690 $result = '';
692 if (strpos($code, '*') !== false) {
693 return('');
696 $code = strtoupper($code);
698 // start : *
699 $result .= self::$encoding[47];
701 // digits
702 $len = strlen($code);
703 for ($i=0; $i<$len; $i++) {
704 $c = $code[$i];
705 $index = strpos($table, $c);
706 if (($c == '_') || ($index === false)) {
707 return('');
710 $result .= self::$encoding[ $index ];
713 // checksum
714 if ($crc) {
715 $weightC = 0;
716 $weightSumC = 0;
717 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
718 $weightSumK = 0;
719 for ($i=$len-1; $i>-1; $i--) {
720 $weightC = $weightC == 20 ? 1 : $weightC + 1;
721 $weightK = $weightK == 15 ? 1 : $weightK + 1;
723 $index = strpos($table, $code[$i]);
725 $weightSumC += $weightC * $index;
726 $weightSumK += $weightK * $index;
729 $c = $weightSumC % 47;
730 $weightSumK += $c;
731 $k = $weightSumK % 47;
733 $result .= self::$encoding[$c];
734 $result .= self::$encoding[$k];
737 // stop : *
738 $result .= self::$encoding[47];
740 // Terminaison bar
741 $result .= '1';
742 return($result);
746 class Barcode128
748 static private $encoding = array(
749 '11011001100', '11001101100', '11001100110', '10010011000',
750 '10010001100', '10001001100', '10011001000', '10011000100',
751 '10001100100', '11001001000', '11001000100', '11000100100',
752 '10110011100', '10011011100', '10011001110', '10111001100',
753 '10011101100', '10011100110', '11001110010', '11001011100',
754 '11001001110', '11011100100', '11001110100', '11101101110',
755 '11101001100', '11100101100', '11100100110', '11101100100',
756 '11100110100', '11100110010', '11011011000', '11011000110',
757 '11000110110', '10100011000', '10001011000', '10001000110',
758 '10110001000', '10001101000', '10001100010', '11010001000',
759 '11000101000', '11000100010', '10110111000', '10110001110',
760 '10001101110', '10111011000', '10111000110', '10001110110',
761 '11101110110', '11010001110', '11000101110', '11011101000',
762 '11011100010', '11011101110', '11101011000', '11101000110',
763 '11100010110', '11101101000', '11101100010', '11100011010',
764 '11101111010', '11001000010', '11110001010', '10100110000',
765 '10100001100', '10010110000', '10010000110', '10000101100',
766 '10000100110', '10110010000', '10110000100', '10011010000',
767 '10011000010', '10000110100', '10000110010', '11000010010',
768 '11001010000', '11110111010', '11000010100', '10001111010',
769 '10100111100', '10010111100', '10010011110', '10111100100',
770 '10011110100', '10011110010', '11110100100', '11110010100',
771 '11110010010', '11011011110', '11011110110', '11110110110',
772 '10101111000', '10100011110', '10001011110', '10111101000',
773 '10111100010', '11110101000', '11110100010', '10111011110',
774 '10111101110', '11101011110', '11110101110', '11010000100',
775 '11010010000', '11010011100', '11000111010');
776 public static function getDigit($code)
778 $tableB = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
779 $result = "";
780 $sum = 0;
781 $isum = 0;
782 $i = 0;
783 $j = 0;
784 $value = 0;
786 // check each characters
787 $len = strlen($code);
788 for ($i=0; $i<$len; $i++) {
789 if (strpos($tableB, $code[$i]) === false) {
790 return("");
794 // check firsts characters : start with C table only if enought numeric
795 $tableCActivated = $len> 1;
796 $c = '';
797 for ($i=0; $i<3 && $i<$len; $i++) {
798 $tableCActivated &= preg_match('`[0-9]`', $code[$i]);
801 $sum = $tableCActivated ? 105 : 104;
803 // start : [105] : C table or [104] : B table
804 $result = self::$encoding[ $sum ];
806 $i = 0;
807 while ($i < $len) {
808 if (! $tableCActivated) {
809 $j = 0;
810 // check next character to activate C table if interresting
811 while (($i + $j < $len) && preg_match('`[0-9]`', $code[$i+$j])) {
812 $j++;
815 // 6 min everywhere or 4 mini at the end
816 $tableCActivated = ($j > 5) || (($i + $j - 1 == $len) && ($j > 3));
818 if ($tableCActivated) {
819 $result .= self::$encoding[ 99 ]; // C table
820 $sum += ++$isum * 99;
823 // 2 min for table C so need table B
824 } else if (($i == $len - 1) || (preg_match('`[^0-9]`', $code[$i])) || (preg_match('`[^0-9]`', $code[$i+1]))) { //todo : verifier le JS : len - 1!!! XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
825 $tableCActivated = false;
826 $result .= self::$encoding[ 100 ]; // B table
827 $sum += ++$isum * 100;
830 if ($tableCActivated) {
831 $value = intval(substr($code, $i, 2)); // Add two characters (numeric)
832 $i += 2;
833 } else {
834 $value = strpos($tableB, $code[$i]); // Add one character
835 $i++;
838 $result .= self::$encoding[ $value ];
839 $sum += ++$isum * $value;
842 // Add CRC
843 $result .= self::$encoding[ $sum % 103 ];
845 // Stop
846 $result .= self::$encoding[ 106 ];
848 // Termination bar
849 $result .= '11';
851 return($result);
855 class BarcodeCodabar
857 static private $encoding = array(
858 '101010011', '101011001', '101001011', '110010101',
859 '101101001', '110101001', '100101011', '100101101',
860 '100110101', '110100101', '101001101', '101100101',
861 '1101011011', '1101101011', '1101101101', '1011011011',
862 '1011001001', '1010010011', '1001001011', '1010011001');
864 public static function getDigit($code)
866 $table = '0123456789-$:/.+';
867 $result = '';
868 $intercharacter = '0';
870 // add start : A->D : arbitrary choose A
871 $result .= self::$encoding[16] . $intercharacter;
873 $len = strlen($code);
874 for ($i=0; $i<$len; $i++) {
875 $index = strpos($table, $code[$i]);
876 if ($index === false) {
877 return('');
880 $result .= self::$encoding[ $index ] . $intercharacter;
883 // add stop : A->D : arbitrary choose A
884 $result .= self::$encoding[16];
885 return($result);
889 class BarcodeDatamatrix
891 static private $lengthRows = array(
892 10, 12, 14, 16, 18, 20, 22, 24, 26, // 24 squares et 6 rectangular
893 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
894 8, 8, 12, 12, 16, 16);
895 static private $lengthCols = array(
896 10, 12, 14, 16, 18, 20, 22, 24, 26, // Number of columns for the entire datamatrix
897 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
898 18, 32, 26, 36, 36, 48);
899 static private $dataCWCount = array(
900 3, 5, 8, 12, 18, 22, 30, 36, // Number of data codewords for the datamatrix
901 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816, 1050,
902 1304, 1558, 5, 10, 16, 22, 32, 49);
903 static private $solomonCWCount = array(
904 5, 7, 10, 12, 14, 18, 20, 24, 28, // Number of Reed-Solomon codewords for the datamatrix
905 36, 42, 48, 56, 68, 84, 112, 144, 192, 224, 272, 336, 408, 496, 620,
906 7, 11, 14, 18, 24, 28);
907 static private $dataRegionRows = array(
908 8, 10, 12, 14, 16, 18, 20, 22, // Number of rows per region
909 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
910 6, 6, 10, 10, 14, 14);
911 static private $dataRegionCols = array(
912 8, 10, 12, 14, 16, 18, 20, 22, // Number of columns per region
913 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
914 16, 14, 24, 16, 16, 22);
915 static private $regionRows = array(
916 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per row
917 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
918 1, 1, 1, 1, 1, 1);
919 static private $regionCols = array(
920 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per column
921 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
922 1, 2, 1, 2, 2, 2);
923 static private $interleavedBlocks = array(
924 1, 1, 1, 1, 1, 1, 1, 1, // Number of blocks
925 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 6, 6, 8, 8,
926 1, 1, 1, 1, 1, 1);
927 static private $logTab = array(
928 -255, 255, 1, 240, 2, 225, 241, 53, 3, // Table of log for the Galois field
929 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106, 134, 28,
930 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115,
931 103, 228, 78, 107, 125, 135, 8, 29, 162, 244, 186, 141, 180, 45, 99,
932 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76, 220, 217, 197,
933 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171,
934 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187,
935 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, 57, 147,
936 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7,
937 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
938 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194,
939 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127,
940 247, 146, 66, 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73,
941 164, 144, 85, 170, 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82,
942 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112,
943 232, 21, 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149,
944 129, 19, 155, 59, 249, 70, 214, 250, 168, 71, 201, 156, 64, 60, 237,
945 130, 111, 20, 93, 122, 177, 150);
946 static private $aLogTab = array(
947 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, // Table of aLog for the Galois field
948 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219, 155, 27, 54,
949 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36,
950 72, 144, 13, 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56,
951 112, 224, 237, 247, 195, 171, 123, 246, 193, 175, 115, 230, 225, 239,
952 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190,
953 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106,
954 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, 217, 159, 19, 38, 76,
955 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223,
956 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113,
957 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, 214, 129,
958 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, 127,
959 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
960 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161,
961 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132,
962 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248,
963 221, 151, 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75,
964 150, 1);
965 private static function champGaloisMult($a, $b)
967 // MULTIPLICATION IN GALOIS FIELD GF(2^8)
968 if (!$a || !$b) {
969 return 0;
972 return self::$aLogTab[(self::$logTab[$a] + self::$logTab[$b]) % 255];
974 private static function champGaloisDoub($a, $b)
976 // THE OPERATION a * 2^b IN GALOIS FIELD GF(2^8)
977 if (!$a) {
978 return 0;
981 if (!$b) {
982 return $a;
985 return self::$aLogTab[(self::$logTab[$a] + $b) % 255];
987 private static function champGaloisSum($a, $b)
989 // SUM IN GALOIS FIELD GF(2^8)
990 return $a ^ $b;
992 private static function selectIndex($dataCodeWordsCount, $rectangular)
994 // CHOOSE THE GOOD INDEX FOR TABLES
995 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>1558) && !$rectangular) {
996 return -1;
999 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>49) && $rectangular) {
1000 return -1;
1003 $n = $rectangular ? 24 : 0;
1005 while (self::$dataCWCount[$n] < $dataCodeWordsCount) {
1006 $n++;
1009 return $n;
1011 private static function encodeDataCodeWordsASCII($text)
1013 $dataCodeWords = array();
1014 $n = 0;
1015 $len = strlen($text);
1016 for ($i=0; $i<$len; $i++) {
1017 $c = ord($text[$i]);
1018 if ($c > 127) {
1019 $dataCodeWords[$n] = 235;
1020 $c -= 127;
1021 $n++;
1022 } else if (($c>=48 && $c<=57) && ($i+1<$len) && (preg_match('`[0-9]`', $text[$i+1]))) {
1023 $c = (($c - 48) * 10) + intval($text[$i+1]);
1024 $c += 130;
1025 $i++;
1026 } else {
1027 $c++;
1030 $dataCodeWords[$n] = $c;
1031 $n++;
1034 return $dataCodeWords;
1036 private static function addPadCW(&$tab, $from, $to)
1038 if ($from >= $to) {
1039 return ;
1042 $tab[$from] = 129;
1043 for ($i=$from+1; $i<$to; $i++) {
1044 $r = ((149 * ($i+1)) % 253) + 1;
1045 $tab[$i] = (129 + $r) % 254;
1048 private static function calculSolFactorTable($solomonCWCount)
1050 // CALCULATE THE REED SOLOMON FACTORS
1051 $g = array_fill(0, $solomonCWCount+1, 1);
1052 for ($i = 1; $i <= $solomonCWCount; $i++) {
1053 for ($j = $i - 1; $j >= 0; $j--) {
1054 $g[$j] = self::champGaloisDoub($g[$j], $i);
1055 if ($j > 0) {
1056 $g[$j] = self::champGaloisSum($g[$j], $g[$j-1]);
1061 return $g;
1063 private static function addReedSolomonCW($nSolomonCW, $coeffTab, $nDataCW, &$dataTab, $blocks)
1065 // Add the Reed Solomon codewords
1066 $errorBlocks = $nSolomonCW / $blocks;
1067 $correctionCW = array();
1069 for ($k = 0; $k < $blocks; $k++) {
1070 for ($i=0; $i < $errorBlocks; $i++) {
1071 $correctionCW[$i] = 0;
1074 for ($i=$k; $i<$nDataCW; $i+=$blocks) {
1075 $temp = self::champGaloisSum($dataTab[$i], $correctionCW[$errorBlocks-1]);
1076 for ($j=$errorBlocks-1; $j>=0; $j--) {
1077 if (!$temp) {
1078 $correctionCW[$j] = 0;
1079 } else {
1080 $correctionCW[$j] = self::champGaloisMult($temp, $coeffTab[$j]);
1083 if ($j>0) {
1084 $correctionCW[$j] = self::champGaloisSum($correctionCW[$j-1], $correctionCW[$j]);
1089 // Renversement des blocs calcules
1090 $j = $nDataCW + $k;
1091 for ($i=$errorBlocks-1; $i>=0; $i--) {
1092 $dataTab[$j] = $correctionCW[$i];
1093 $j=$j+$blocks;
1097 return $dataTab;
1099 private static function getBits($entier)
1101 // Transform integer to tab of bits
1102 $bits = array();
1103 for ($i=0; $i<8; $i++) {
1104 $bits[$i] = $entier & (128 >> $i) ? 1 : 0;
1107 return $bits;
1109 private static function next($etape, $totalRows, $totalCols, $codeWordsBits, &$datamatrix, &$assigned)
1111 // Place codewords into the matrix
1112 $chr = 0; // Place of the 8st bit from the first character to [4][0]
1113 $row = 4;
1114 $col = 0;
1116 do {
1117 // Check for a special case of corner
1118 if (($row == $totalRows) && ($col == 0)) {
1119 self::patternShapeSpecial1($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1120 $chr++;
1121 } else if (($etape<3) && ($row == $totalRows-2) && ($col == 0) && ($totalCols%4 != 0)) {
1122 self::patternShapeSpecial2($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1123 $chr++;
1124 } else if (($row == $totalRows-2) && ($col == 0) && ($totalCols%8 == 4)) {
1125 self::patternShapeSpecial3($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1126 $chr++;
1127 } else if (($row == $totalRows+4) && ($col == 2) && ($totalCols%8 == 0)) {
1128 self::patternShapeSpecial4($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1129 $chr++;
1132 // Go up and right in the datamatrix
1133 do {
1134 if (($row < $totalRows) && ($col >= 0) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)) {
1135 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1136 $chr++;
1139 $row -= 2;
1140 $col += 2;
1141 } while (($row >= 0) && ($col < $totalCols));
1142 $row += 1;
1143 $col += 3;
1145 // Go down and left in the datamatrix
1146 do {
1147 if (($row >= 0) && ($col < $totalCols) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)) {
1148 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1149 $chr++;
1152 $row += 2;
1153 $col -= 2;
1154 } while (($row < $totalRows) && ($col >=0));
1155 $row += 3;
1156 $col += 1;
1157 } while (($row < $totalRows) || ($col < $totalCols));
1159 private static function patternShapeStandard(&$datamatrix, &$assigned, $bits, $row, $col, $totalRows, $totalCols)
1161 // Place bits in the matrix (standard or special case)
1162 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $row-2, $col-2, $totalRows, $totalCols);
1163 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $row-2, $col-1, $totalRows, $totalCols);
1164 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $row-1, $col-2, $totalRows, $totalCols);
1165 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], $row-1, $col-1, $totalRows, $totalCols);
1166 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], $row-1, $col, $totalRows, $totalCols);
1167 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], $row, $col-2, $totalRows, $totalCols);
1168 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], $row, $col-1, $totalRows, $totalCols);
1169 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], $row, $col, $totalRows, $totalCols);
1171 private static function patternShapeSpecial1(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1173 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1174 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, 1, $totalRows, $totalCols);
1175 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 2, $totalRows, $totalCols);
1176 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1177 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1178 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1179 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1180 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1182 private static function patternShapeSpecial2(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1184 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1185 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1186 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1187 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-4, $totalRows, $totalCols);
1188 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-3, $totalRows, $totalCols);
1189 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 0, $totalCols-2, $totalRows, $totalCols);
1190 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 0, $totalCols-1, $totalRows, $totalCols);
1191 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1193 private static function patternShapeSpecial3(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1195 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1196 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1197 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1198 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1199 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1200 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1201 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1202 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1204 private static function patternShapeSpecial4(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1206 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1207 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, $totalCols-1, $totalRows, $totalCols);
1208 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], 0, $totalCols-3, $totalRows, $totalCols);
1209 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1210 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1211 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-3, $totalRows, $totalCols);
1212 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 1, $totalCols-2, $totalRows, $totalCols);
1213 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1215 private static function placeBitInDatamatrix(&$datamatrix, &$assigned, $bit, $row, $col, $totalRows, $totalCols)
1217 // Put a bit into the matrix
1218 if ($row < 0) {
1219 $row += $totalRows;
1220 $col += 4 - (($totalRows+4)%8);
1223 if ($col < 0) {
1224 $col += $totalCols;
1225 $row += 4 - (($totalCols+4)%8);
1228 if (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1) {
1229 $datamatrix[$row][$col] = $bit;
1230 $assigned[$row][$col] = 1;
1233 private static function addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW)
1235 // Add the finder pattern
1236 $totalRowsCW = ($rowsRegionCW+2) * $rowsRegion;
1237 $totalColsCW = ($colsRegionCW+2) * $colsRegion;
1239 $datamatrixTemp = array();
1240 $datamatrixTemp[0] = array_fill(0, $totalColsCW+2, 0);
1242 for ($i=0; $i<$totalRowsCW; $i++) {
1243 $datamatrixTemp[$i+1] = array();
1244 $datamatrixTemp[$i+1][0] = 0;
1245 $datamatrixTemp[$i+1][$totalColsCW+1] = 0;
1246 for ($j=0; $j<$totalColsCW; $j++) {
1247 if ($i%($rowsRegionCW+2) == 0) {
1248 if ($j%2 == 0) {
1249 $datamatrixTemp[$i+1][$j+1] = 1;
1250 } else {
1251 $datamatrixTemp[$i+1][$j+1] = 0;
1253 } else if ($i%($rowsRegionCW+2) == $rowsRegionCW+1) {
1254 $datamatrixTemp[$i+1][$j+1] = 1;
1255 } else if ($j%($colsRegionCW+2) == $colsRegionCW+1) {
1256 if ($i%2 == 0) {
1257 $datamatrixTemp[$i+1][$j+1] = 0;
1258 } else {
1259 $datamatrixTemp[$i+1][$j+1] = 1;
1261 } else if ($j%($colsRegionCW+2) == 0) {
1262 $datamatrixTemp[$i+1][$j+1] = 1;
1263 } else {
1264 $datamatrixTemp[$i+1][$j+1] = 0;
1265 $datamatrixTemp[$i+1][$j+1] = $datamatrix[$i-1-(2*(floor($i/($rowsRegionCW+2))))][$j-1-(2*(floor($j/($colsRegionCW+2))))]; // todo : parseInt => ?
1270 $datamatrixTemp[$totalRowsCW+1] = array();
1271 for ($j=0; $j<$totalColsCW+2; $j++) {
1272 $datamatrixTemp[$totalRowsCW+1][$j] = 0;
1275 return $datamatrixTemp;
1277 public static function getDigit($text, $rectangular)
1279 $dataCodeWords = self::encodeDataCodeWordsASCII($text); // Code the text in the ASCII mode
1280 $dataCWCount = count($dataCodeWords);
1281 $index = self::selectIndex($dataCWCount, $rectangular); // Select the index for the data tables
1282 $totalDataCWCount = self::$dataCWCount[$index]; // Number of data CW
1283 $solomonCWCount = self::$solomonCWCount[$index]; // Number of Reed Solomon CW
1284 $totalCWCount = $totalDataCWCount + $solomonCWCount; // Number of CW
1285 $rowsTotal = self::$lengthRows[$index]; // Size of symbol
1286 $colsTotal = self::$lengthCols[$index];
1287 $rowsRegion = self::$regionRows[$index]; // Number of region
1288 $colsRegion = self::$regionCols[$index];
1289 $rowsRegionCW = self::$dataRegionRows[$index];
1290 $colsRegionCW = self::$dataRegionCols[$index];
1291 $rowsLengthMatrice = $rowsTotal-2*$rowsRegion; // Size of matrice data
1292 $colsLengthMatrice = $colsTotal-2*$colsRegion;
1293 $blocks = self::$interleavedBlocks[$index]; // Number of Reed Solomon blocks
1294 $errorBlocks = $solomonCWCount / $blocks;
1296 self::addPadCW($dataCodeWords, $dataCWCount, $totalDataCWCount); // Add codewords pads
1298 $g = self::calculSolFactorTable($errorBlocks); // Calculate correction coefficients
1300 self::addReedSolomonCW($solomonCWCount, $g, $totalDataCWCount, $dataCodeWords, $blocks); // Add Reed Solomon codewords
1302 $codeWordsBits = array(); // Calculte bits from codewords
1303 for ($i=0; $i<$totalCWCount; $i++) {
1304 $codeWordsBits[$i] = self::getBits($dataCodeWords[$i]);
1307 $datamatrix = array_fill(0, $colsLengthMatrice, array());
1308 $assigned = array_fill(0, $colsLengthMatrice, array());
1310 // Add the bottom-right corner if needed
1311 if ((($rowsLengthMatrice * $colsLengthMatrice) % 8) == 4) {
1312 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1313 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1314 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 0;
1315 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 0;
1316 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1317 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1318 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 1;
1319 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 1;
1322 // Put the codewords into the matrix
1323 self::next(0, $rowsLengthMatrice, $colsLengthMatrice, $codeWordsBits, $datamatrix, $assigned);
1325 // Add the finder pattern
1326 $datamatrix = self::addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW);
1328 return $datamatrix;