fix: Update patient_tracker.php (#6595)
[openemr.git] / library / classes / php-barcode.php
blobf2aac7d1f61eb0bda36d47ec759b13da513bf60d
1 <?php
3 /*
4 * BarCode Coder Library (BCC Library)
5 * BCCL Version 2.0
7 * Porting : PHP
8 * Version : 2.0.3
10 * Date : 2013-01-06
11 * Author : DEMONTE Jean-Baptiste <jbdemonte@gmail.com>
12 * HOUREZ Jonathan
14 * Web site: https://barcode-coder.com/
15 * dual licence : https://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
16 * https://www.gnu.org/licenses/gpl.html
17 * BarCode Coder Library
18 * @package BCC Library
19 * @author DEMONTE Jean-Baptiste <jbdemonte@gmail.com>
20 * @author HOUREZ Jonathan
21 * @copyright 2013
23 * Added to Openemr by Terry Hill terry@lillysystems.com
24 * this is from the barcode-coder website
29 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 } elseif ($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 } elseif ($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
456 public static function getDigit($code)
458 if (strlen($code) < 12) {
459 $code = '0' . $code;
462 return BarcodeEAN::getDigit($code, 'ean13');
465 public static function compute($code)
467 if (strlen($code) < 12) {
468 $code = '0' . $code;
471 return substr(BarcodeEAN::compute($code, 'ean13'), 1);
475 class BarcodeMSI
477 static private $encoding = array(
478 '100100100100', '100100100110', '100100110100', '100100110110',
479 '100110100100', '100110100110', '100110110100', '100110110110',
480 '110100100100', '110100100110');
482 public static function compute($code, $crc)
484 if (is_array($crc)) {
485 if ($crc['crc1'] == 'mod10') {
486 $code = self::computeMod10($code);
487 } elseif ($crc['crc1'] == 'mod11') {
488 $code = self::computeMod11($code);
491 if ($crc['crc2'] == 'mod10') {
492 $code = self::computeMod10($code);
493 } elseif ($crc['crc2'] == 'mod11') {
494 $code = self::computeMod11($code);
496 } elseif ($crc) {
497 $code = self::computeMod10($code);
500 return($code);
503 private static function computeMod10($code)
505 $len = strlen($code);
506 $toPart1 = $len % 2;
507 $n1 = 0;
508 $sum = 0;
509 for ($i = 0; $i < $len; $i++) {
510 if ($toPart1) {
511 $n1 = 10 * $n1 + intval($code[$i]);
512 } else {
513 $sum += intval($code[$i]);
516 $toPart1 = ! $toPart1;
519 $s1 = (string) (2 * $n1);
520 $len = strlen($s1);
521 for ($i = 0; $i < $len; $i++) {
522 $sum += intval($s1[$i]);
525 return($code . ( (string) (10 - $sum % 10) % 10));
528 private static function computeMod11($code)
530 $sum = 0;
531 $weight = 2;
532 for ($i = strlen($code) - 1; $i > -1; $i--) {
533 $sum += $weight * intval($code[$i]);
534 $weight = $weight == 7 ? 2 : $weight + 1;
537 return($code . ( (string) (11 - $sum % 11) % 11) );
540 public static function getDigit($code, $crc)
542 if (preg_match('`[^0-9]`', $code)) {
543 return '';
546 $index = 0;
547 $result = '';
549 $code = self::compute($code, false);
551 // start
552 $result = '110';
554 // digits
555 $len = strlen($code);
556 for ($i = 0; $i < $len; $i++) {
557 $result .= self::$encoding[ intval($code[$i]) ];
560 // stop
561 $result .= '1001';
563 return($result);
567 class Barcode11
569 static private $encoding = array(
570 '101011', '1101011', '1001011', '1100101',
571 '1011011', '1101101', '1001101', '1010011',
572 '1101001', '110101', '101101');
574 public static function getDigit($code)
576 if (preg_match('`[^0-9\-]`', $code)) {
577 return '';
580 $result = '';
581 $intercharacter = '0';
583 // start
584 $result = '1011001' . $intercharacter;
586 // digits
587 $len = strlen($code);
588 for ($i = 0; $i < $len; $i++) {
589 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
590 $result .= self::$encoding[ $index ] . $intercharacter;
593 // checksum
594 $weightC = 0;
595 $weightSumC = 0;
596 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
597 $weightSumK = 0;
598 for ($i = $len - 1; $i > -1; $i--) {
599 $weightC = $weightC == 10 ? 1 : $weightC + 1;
600 $weightK = $weightK == 10 ? 1 : $weightK + 1;
602 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
604 $weightSumC += $weightC * $index;
605 $weightSumK += $weightK * $index;
608 $c = $weightSumC % 11;
609 $weightSumK += $c;
610 $k = $weightSumK % 11;
612 $result .= self::$encoding[$c] . $intercharacter;
614 if ($len >= 10) {
615 $result .= self::$encoding[$k] . $intercharacter;
618 // stop
619 $result .= '1011001';
621 return($result);
625 class Barcode39
627 static private $encoding = array(
628 '101001101101', '110100101011', '101100101011', '110110010101',
629 '101001101011', '110100110101', '101100110101', '101001011011',
630 '110100101101', '101100101101', '110101001011', '101101001011',
631 '110110100101', '101011001011', '110101100101', '101101100101',
632 '101010011011', '110101001101', '101101001101', '101011001101',
633 '110101010011', '101101010011', '110110101001', '101011010011',
634 '110101101001', '101101101001', '101010110011', '110101011001',
635 '101101011001', '101011011001', '110010101011', '100110101011',
636 '110011010101', '100101101011', '110010110101', '100110110101',
637 '100101011011', '110010101101', '100110101101', '100100100101',
638 '100100101001', '100101001001', '101001001001', '100101101101');
639 public static function getDigit($code)
641 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*';
642 $result = '';
643 $intercharacter = '0';
645 if (strpos($code, '*') !== false) {
646 return('');
649 // Add Start and Stop charactere : *
650 $code = strtoupper('*' . $code . '*');
652 $len = strlen($code);
653 for ($i = 0; $i < $len; $i++) {
654 $index = strpos($table, $code[$i]);
655 if ($index === false) {
656 return('');
659 if ($i > 0) {
660 $result .= $intercharacter;
663 $result .= self::$encoding[ $index ];
666 return($result);
670 class Barcode93
672 static private $encoding = array(
673 '100010100', '101001000', '101000100', '101000010',
674 '100101000', '100100100', '100100010', '101010000',
675 '100010010', '100001010', '110101000', '110100100',
676 '110100010', '110010100', '110010010', '110001010',
677 '101101000', '101100100', '101100010', '100110100',
678 '100011010', '101011000', '101001100', '101000110',
679 '100101100', '100010110', '110110100', '110110010',
680 '110101100', '110100110', '110010110', '110011010',
681 '101101100', '101100110', '100110110', '100111010',
682 '100101110', '111010100', '111010010', '111001010',
683 '101101110', '101110110', '110101110', '100100110',
684 '111011010', '111010110', '100110010', '101011110');
686 public static function getDigit($code, $crc)
688 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%____*'; // _ => ($), (%), (/) et (+)
689 $result = '';
691 if (strpos($code, '*') !== false) {
692 return('');
695 $code = strtoupper($code);
697 // start : *
698 $result .= self::$encoding[47];
700 // digits
701 $len = strlen($code);
702 for ($i = 0; $i < $len; $i++) {
703 $c = $code[$i];
704 $index = strpos($table, $c);
705 if (($c == '_') || ($index === false)) {
706 return('');
709 $result .= self::$encoding[ $index ];
712 // checksum
713 if ($crc) {
714 $weightC = 0;
715 $weightSumC = 0;
716 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
717 $weightSumK = 0;
718 for ($i = $len - 1; $i > -1; $i--) {
719 $weightC = $weightC == 20 ? 1 : $weightC + 1;
720 $weightK = $weightK == 15 ? 1 : $weightK + 1;
722 $index = strpos($table, $code[$i]);
724 $weightSumC += $weightC * $index;
725 $weightSumK += $weightK * $index;
728 $c = $weightSumC % 47;
729 $weightSumK += $c;
730 $k = $weightSumK % 47;
732 $result .= self::$encoding[$c];
733 $result .= self::$encoding[$k];
736 // stop : *
737 $result .= self::$encoding[47];
739 // Terminaison bar
740 $result .= '1';
741 return($result);
745 class Barcode128
747 static private $encoding = array(
748 '11011001100', '11001101100', '11001100110', '10010011000',
749 '10010001100', '10001001100', '10011001000', '10011000100',
750 '10001100100', '11001001000', '11001000100', '11000100100',
751 '10110011100', '10011011100', '10011001110', '10111001100',
752 '10011101100', '10011100110', '11001110010', '11001011100',
753 '11001001110', '11011100100', '11001110100', '11101101110',
754 '11101001100', '11100101100', '11100100110', '11101100100',
755 '11100110100', '11100110010', '11011011000', '11011000110',
756 '11000110110', '10100011000', '10001011000', '10001000110',
757 '10110001000', '10001101000', '10001100010', '11010001000',
758 '11000101000', '11000100010', '10110111000', '10110001110',
759 '10001101110', '10111011000', '10111000110', '10001110110',
760 '11101110110', '11010001110', '11000101110', '11011101000',
761 '11011100010', '11011101110', '11101011000', '11101000110',
762 '11100010110', '11101101000', '11101100010', '11100011010',
763 '11101111010', '11001000010', '11110001010', '10100110000',
764 '10100001100', '10010110000', '10010000110', '10000101100',
765 '10000100110', '10110010000', '10110000100', '10011010000',
766 '10011000010', '10000110100', '10000110010', '11000010010',
767 '11001010000', '11110111010', '11000010100', '10001111010',
768 '10100111100', '10010111100', '10010011110', '10111100100',
769 '10011110100', '10011110010', '11110100100', '11110010100',
770 '11110010010', '11011011110', '11011110110', '11110110110',
771 '10101111000', '10100011110', '10001011110', '10111101000',
772 '10111100010', '11110101000', '11110100010', '10111011110',
773 '10111101110', '11101011110', '11110101110', '11010000100',
774 '11010010000', '11010011100', '11000111010');
775 public static function getDigit($code)
777 $tableB = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
778 $result = "";
779 $sum = 0;
780 $isum = 0;
781 $i = 0;
782 $j = 0;
783 $value = 0;
785 // check each characters
786 $len = strlen($code);
787 for ($i = 0; $i < $len; $i++) {
788 if (strpos($tableB, $code[$i]) === false) {
789 return("");
793 // check firsts characters : start with C table only if enought numeric
794 $tableCActivated = $len > 1;
795 $c = '';
796 for ($i = 0; $i < 3 && $i < $len; $i++) {
797 $tableCActivated &= preg_match('`[0-9]`', $code[$i]);
800 $sum = $tableCActivated ? 105 : 104;
802 // start : [105] : C table or [104] : B table
803 $result = self::$encoding[ $sum ];
805 $i = 0;
806 while ($i < $len) {
807 if (! $tableCActivated) {
808 $j = 0;
809 // check next character to activate C table if interresting
810 while (($i + $j < $len) && preg_match('`[0-9]`', $code[$i + $j])) {
811 $j++;
814 // 6 min everywhere or 4 mini at the end
815 $tableCActivated = ($j > 5) || (($i + $j - 1 == $len) && ($j > 3));
817 if ($tableCActivated) {
818 $result .= self::$encoding[ 99 ]; // C table
819 $sum += ++$isum * 99;
822 // 2 min for table C so need table B
823 } elseif (($i == $len - 1) || (preg_match('`[^0-9]`', $code[$i])) || (preg_match('`[^0-9]`', $code[$i + 1]))) { //todo : verifier le JS : len - 1!!! XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
824 $tableCActivated = false;
825 $result .= self::$encoding[ 100 ]; // B table
826 $sum += ++$isum * 100;
829 if ($tableCActivated) {
830 $value = intval(substr($code, $i, 2)); // Add two characters (numeric)
831 $i += 2;
832 } else {
833 $value = strpos($tableB, $code[$i]); // Add one character
834 $i++;
837 $result .= self::$encoding[ $value ];
838 $sum += ++$isum * $value;
841 // Add CRC
842 $result .= self::$encoding[ $sum % 103 ];
844 // Stop
845 $result .= self::$encoding[ 106 ];
847 // Termination bar
848 $result .= '11';
850 return($result);
854 class BarcodeCodabar
856 static private $encoding = array(
857 '101010011', '101011001', '101001011', '110010101',
858 '101101001', '110101001', '100101011', '100101101',
859 '100110101', '110100101', '101001101', '101100101',
860 '1101011011', '1101101011', '1101101101', '1011011011',
861 '1011001001', '1010010011', '1001001011', '1010011001');
863 public static function getDigit($code)
865 $table = '0123456789-$:/.+';
866 $result = '';
867 $intercharacter = '0';
869 // add start : A->D : arbitrary choose A
870 $result .= self::$encoding[16] . $intercharacter;
872 $len = strlen($code);
873 for ($i = 0; $i < $len; $i++) {
874 $index = strpos($table, $code[$i]);
875 if ($index === false) {
876 return('');
879 $result .= self::$encoding[ $index ] . $intercharacter;
882 // add stop : A->D : arbitrary choose A
883 $result .= self::$encoding[16];
884 return($result);
888 class BarcodeDatamatrix
890 static private $lengthRows = array(
891 10, 12, 14, 16, 18, 20, 22, 24, 26, // 24 squares et 6 rectangular
892 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
893 8, 8, 12, 12, 16, 16);
894 static private $lengthCols = array(
895 10, 12, 14, 16, 18, 20, 22, 24, 26, // Number of columns for the entire datamatrix
896 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
897 18, 32, 26, 36, 36, 48);
898 static private $dataCWCount = array(
899 3, 5, 8, 12, 18, 22, 30, 36, // Number of data codewords for the datamatrix
900 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816, 1050,
901 1304, 1558, 5, 10, 16, 22, 32, 49);
902 static private $solomonCWCount = array(
903 5, 7, 10, 12, 14, 18, 20, 24, 28, // Number of Reed-Solomon codewords for the datamatrix
904 36, 42, 48, 56, 68, 84, 112, 144, 192, 224, 272, 336, 408, 496, 620,
905 7, 11, 14, 18, 24, 28);
906 static private $dataRegionRows = array(
907 8, 10, 12, 14, 16, 18, 20, 22, // Number of rows per region
908 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
909 6, 6, 10, 10, 14, 14);
910 static private $dataRegionCols = array(
911 8, 10, 12, 14, 16, 18, 20, 22, // Number of columns per region
912 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
913 16, 14, 24, 16, 16, 22);
914 static private $regionRows = array(
915 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per row
916 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
917 1, 1, 1, 1, 1, 1);
918 static private $regionCols = array(
919 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per column
920 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
921 1, 2, 1, 2, 2, 2);
922 static private $interleavedBlocks = array(
923 1, 1, 1, 1, 1, 1, 1, 1, // Number of blocks
924 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 6, 6, 8, 8,
925 1, 1, 1, 1, 1, 1);
926 static private $logTab = array(
927 -255, 255, 1, 240, 2, 225, 241, 53, 3, // Table of log for the Galois field
928 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106, 134, 28,
929 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115,
930 103, 228, 78, 107, 125, 135, 8, 29, 162, 244, 186, 141, 180, 45, 99,
931 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76, 220, 217, 197,
932 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171,
933 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187,
934 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, 57, 147,
935 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7,
936 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
937 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194,
938 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127,
939 247, 146, 66, 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73,
940 164, 144, 85, 170, 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82,
941 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112,
942 232, 21, 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149,
943 129, 19, 155, 59, 249, 70, 214, 250, 168, 71, 201, 156, 64, 60, 237,
944 130, 111, 20, 93, 122, 177, 150);
945 static private $aLogTab = array(
946 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, // Table of aLog for the Galois field
947 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219, 155, 27, 54,
948 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36,
949 72, 144, 13, 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56,
950 112, 224, 237, 247, 195, 171, 123, 246, 193, 175, 115, 230, 225, 239,
951 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190,
952 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106,
953 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, 217, 159, 19, 38, 76,
954 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223,
955 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113,
956 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, 214, 129,
957 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, 127,
958 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
959 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161,
960 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132,
961 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248,
962 221, 151, 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75,
963 150, 1);
964 private static function champGaloisMult($a, $b)
966 // MULTIPLICATION IN GALOIS FIELD GF(2^8)
967 if (!$a || !$b) {
968 return 0;
971 return self::$aLogTab[(self::$logTab[$a] + self::$logTab[$b]) % 255];
973 private static function champGaloisDoub($a, $b)
975 // THE OPERATION a * 2^b IN GALOIS FIELD GF(2^8)
976 if (!$a) {
977 return 0;
980 if (!$b) {
981 return $a;
984 return self::$aLogTab[(self::$logTab[$a] + $b) % 255];
986 private static function champGaloisSum($a, $b)
988 // SUM IN GALOIS FIELD GF(2^8)
989 return $a ^ $b;
991 private static function selectIndex($dataCodeWordsCount, $rectangular)
993 // CHOOSE THE GOOD INDEX FOR TABLES
994 if (($dataCodeWordsCount < 1 || $dataCodeWordsCount > 1558) && !$rectangular) {
995 return -1;
998 if (($dataCodeWordsCount < 1 || $dataCodeWordsCount > 49) && $rectangular) {
999 return -1;
1002 $n = $rectangular ? 24 : 0;
1004 while (self::$dataCWCount[$n] < $dataCodeWordsCount) {
1005 $n++;
1008 return $n;
1010 private static function encodeDataCodeWordsASCII($text)
1012 $dataCodeWords = array();
1013 $n = 0;
1014 $len = strlen($text);
1015 for ($i = 0; $i < $len; $i++) {
1016 $c = ord($text[$i]);
1017 if ($c > 127) {
1018 $dataCodeWords[$n] = 235;
1019 $c -= 127;
1020 $n++;
1021 } elseif (($c >= 48 && $c <= 57) && ($i + 1 < $len) && (preg_match('`[0-9]`', $text[$i + 1]))) {
1022 $c = (($c - 48) * 10) + intval($text[$i + 1]);
1023 $c += 130;
1024 $i++;
1025 } else {
1026 $c++;
1029 $dataCodeWords[$n] = $c;
1030 $n++;
1033 return $dataCodeWords;
1035 private static function addPadCW(&$tab, $from, $to)
1037 if ($from >= $to) {
1038 return ;
1041 $tab[$from] = 129;
1042 for ($i = $from + 1; $i < $to; $i++) {
1043 $r = ((149 * ($i + 1)) % 253) + 1;
1044 $tab[$i] = (129 + $r) % 254;
1047 private static function calculSolFactorTable($solomonCWCount)
1049 // CALCULATE THE REED SOLOMON FACTORS
1050 $g = array_fill(0, $solomonCWCount + 1, 1);
1051 for ($i = 1; $i <= $solomonCWCount; $i++) {
1052 for ($j = $i - 1; $j >= 0; $j--) {
1053 $g[$j] = self::champGaloisDoub($g[$j], $i);
1054 if ($j > 0) {
1055 $g[$j] = self::champGaloisSum($g[$j], $g[$j - 1]);
1060 return $g;
1062 private static function addReedSolomonCW($nSolomonCW, $coeffTab, $nDataCW, &$dataTab, $blocks)
1064 // Add the Reed Solomon codewords
1065 $errorBlocks = $nSolomonCW / $blocks;
1066 $correctionCW = array();
1068 for ($k = 0; $k < $blocks; $k++) {
1069 for ($i = 0; $i < $errorBlocks; $i++) {
1070 $correctionCW[$i] = 0;
1073 for ($i = $k; $i < $nDataCW; $i += $blocks) {
1074 $temp = self::champGaloisSum($dataTab[$i], $correctionCW[$errorBlocks - 1]);
1075 for ($j = $errorBlocks - 1; $j >= 0; $j--) {
1076 if (!$temp) {
1077 $correctionCW[$j] = 0;
1078 } else {
1079 $correctionCW[$j] = self::champGaloisMult($temp, $coeffTab[$j]);
1082 if ($j > 0) {
1083 $correctionCW[$j] = self::champGaloisSum($correctionCW[$j - 1], $correctionCW[$j]);
1088 // Renversement des blocs calcules
1089 $j = $nDataCW + $k;
1090 for ($i = $errorBlocks - 1; $i >= 0; $i--) {
1091 $dataTab[$j] = $correctionCW[$i];
1092 $j = $j + $blocks;
1096 return $dataTab;
1098 private static function getBits($entier)
1100 // Transform integer to tab of bits
1101 $bits = array();
1102 for ($i = 0; $i < 8; $i++) {
1103 $bits[$i] = $entier & (128 >> $i) ? 1 : 0;
1106 return $bits;
1108 private static function next($etape, $totalRows, $totalCols, $codeWordsBits, &$datamatrix, &$assigned)
1110 // Place codewords into the matrix
1111 $chr = 0; // Place of the 8st bit from the first character to [4][0]
1112 $row = 4;
1113 $col = 0;
1115 do {
1116 // Check for a special case of corner
1117 if (($row == $totalRows) && ($col == 0)) {
1118 self::patternShapeSpecial1($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1119 $chr++;
1120 } elseif (($etape < 3) && ($row == $totalRows - 2) && ($col == 0) && ($totalCols % 4 != 0)) {
1121 self::patternShapeSpecial2($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1122 $chr++;
1123 } elseif (($row == $totalRows - 2) && ($col == 0) && ($totalCols % 8 == 4)) {
1124 self::patternShapeSpecial3($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1125 $chr++;
1126 } elseif (($row == $totalRows + 4) && ($col == 2) && ($totalCols % 8 == 0)) {
1127 self::patternShapeSpecial4($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1128 $chr++;
1131 // Go up and right in the datamatrix
1132 do {
1133 if (($row < $totalRows) && ($col >= 0) && (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1)) {
1134 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1135 $chr++;
1138 $row -= 2;
1139 $col += 2;
1140 } while (($row >= 0) && ($col < $totalCols));
1141 $row += 1;
1142 $col += 3;
1144 // Go down and left in the datamatrix
1145 do {
1146 if (($row >= 0) && ($col < $totalCols) && (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1)) {
1147 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1148 $chr++;
1151 $row += 2;
1152 $col -= 2;
1153 } while (($row < $totalRows) && ($col >= 0));
1154 $row += 3;
1155 $col += 1;
1156 } while (($row < $totalRows) || ($col < $totalCols));
1158 private static function patternShapeStandard(&$datamatrix, &$assigned, $bits, $row, $col, $totalRows, $totalCols)
1160 // Place bits in the matrix (standard or special case)
1161 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $row - 2, $col - 2, $totalRows, $totalCols);
1162 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $row - 2, $col - 1, $totalRows, $totalCols);
1163 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $row - 1, $col - 2, $totalRows, $totalCols);
1164 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], $row - 1, $col - 1, $totalRows, $totalCols);
1165 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], $row - 1, $col, $totalRows, $totalCols);
1166 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], $row, $col - 2, $totalRows, $totalCols);
1167 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], $row, $col - 1, $totalRows, $totalCols);
1168 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], $row, $col, $totalRows, $totalCols);
1170 private static function patternShapeSpecial1(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1172 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows - 1, 0, $totalRows, $totalCols);
1173 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows - 1, 1, $totalRows, $totalCols);
1174 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows - 1, 2, $totalRows, $totalCols);
1175 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols - 2, $totalRows, $totalCols);
1176 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols - 1, $totalRows, $totalCols);
1177 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols - 1, $totalRows, $totalCols);
1178 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols - 1, $totalRows, $totalCols);
1179 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols - 1, $totalRows, $totalCols);
1181 private static function patternShapeSpecial2(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1183 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows - 3, 0, $totalRows, $totalCols);
1184 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows - 2, 0, $totalRows, $totalCols);
1185 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows - 1, 0, $totalRows, $totalCols);
1186 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols - 4, $totalRows, $totalCols);
1187 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols - 3, $totalRows, $totalCols);
1188 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 0, $totalCols - 2, $totalRows, $totalCols);
1189 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 0, $totalCols - 1, $totalRows, $totalCols);
1190 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols - 1, $totalRows, $totalCols);
1192 private static function patternShapeSpecial3(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1194 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows - 3, 0, $totalRows, $totalCols);
1195 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows - 2, 0, $totalRows, $totalCols);
1196 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows - 1, 0, $totalRows, $totalCols);
1197 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols - 2, $totalRows, $totalCols);
1198 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols - 1, $totalRows, $totalCols);
1199 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols - 1, $totalRows, $totalCols);
1200 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols - 1, $totalRows, $totalCols);
1201 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols - 1, $totalRows, $totalCols);
1203 private static function patternShapeSpecial4(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1205 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows - 1, 0, $totalRows, $totalCols);
1206 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows - 1, $totalCols - 1, $totalRows, $totalCols);
1207 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], 0, $totalCols - 3, $totalRows, $totalCols);
1208 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols - 2, $totalRows, $totalCols);
1209 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols - 1, $totalRows, $totalCols);
1210 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols - 3, $totalRows, $totalCols);
1211 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 1, $totalCols - 2, $totalRows, $totalCols);
1212 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols - 1, $totalRows, $totalCols);
1214 private static function placeBitInDatamatrix(&$datamatrix, &$assigned, $bit, $row, $col, $totalRows, $totalCols)
1216 // Put a bit into the matrix
1217 if ($row < 0) {
1218 $row += $totalRows;
1219 $col += 4 - (($totalRows + 4) % 8);
1222 if ($col < 0) {
1223 $col += $totalCols;
1224 $row += 4 - (($totalCols + 4) % 8);
1227 if (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1) {
1228 $datamatrix[$row][$col] = $bit;
1229 $assigned[$row][$col] = 1;
1232 private static function addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW)
1234 // Add the finder pattern
1235 $totalRowsCW = ($rowsRegionCW + 2) * $rowsRegion;
1236 $totalColsCW = ($colsRegionCW + 2) * $colsRegion;
1238 $datamatrixTemp = array();
1239 $datamatrixTemp[0] = array_fill(0, $totalColsCW + 2, 0);
1241 for ($i = 0; $i < $totalRowsCW; $i++) {
1242 $datamatrixTemp[$i + 1] = array();
1243 $datamatrixTemp[$i + 1][0] = 0;
1244 $datamatrixTemp[$i + 1][$totalColsCW + 1] = 0;
1245 for ($j = 0; $j < $totalColsCW; $j++) {
1246 if ($i % ($rowsRegionCW + 2) == 0) {
1247 if ($j % 2 == 0) {
1248 $datamatrixTemp[$i + 1][$j + 1] = 1;
1249 } else {
1250 $datamatrixTemp[$i + 1][$j + 1] = 0;
1252 } elseif ($i % ($rowsRegionCW + 2) == $rowsRegionCW + 1) {
1253 $datamatrixTemp[$i + 1][$j + 1] = 1;
1254 } elseif ($j % ($colsRegionCW + 2) == $colsRegionCW + 1) {
1255 if ($i % 2 == 0) {
1256 $datamatrixTemp[$i + 1][$j + 1] = 0;
1257 } else {
1258 $datamatrixTemp[$i + 1][$j + 1] = 1;
1260 } elseif ($j % ($colsRegionCW + 2) == 0) {
1261 $datamatrixTemp[$i + 1][$j + 1] = 1;
1262 } else {
1263 $datamatrixTemp[$i + 1][$j + 1] = 0;
1264 $datamatrixTemp[$i + 1][$j + 1] = $datamatrix[$i - 1 - (2 * (floor($i / ($rowsRegionCW + 2))))][$j - 1 - (2 * (floor($j / ($colsRegionCW + 2))))]; // todo : parseInt => ?
1269 $datamatrixTemp[$totalRowsCW + 1] = array();
1270 for ($j = 0; $j < $totalColsCW + 2; $j++) {
1271 $datamatrixTemp[$totalRowsCW + 1][$j] = 0;
1274 return $datamatrixTemp;
1276 public static function getDigit($text, $rectangular)
1278 $dataCodeWords = self::encodeDataCodeWordsASCII($text); // Code the text in the ASCII mode
1279 $dataCWCount = count($dataCodeWords);
1280 $index = self::selectIndex($dataCWCount, $rectangular); // Select the index for the data tables
1281 $totalDataCWCount = self::$dataCWCount[$index]; // Number of data CW
1282 $solomonCWCount = self::$solomonCWCount[$index]; // Number of Reed Solomon CW
1283 $totalCWCount = $totalDataCWCount + $solomonCWCount; // Number of CW
1284 $rowsTotal = self::$lengthRows[$index]; // Size of symbol
1285 $colsTotal = self::$lengthCols[$index];
1286 $rowsRegion = self::$regionRows[$index]; // Number of region
1287 $colsRegion = self::$regionCols[$index];
1288 $rowsRegionCW = self::$dataRegionRows[$index];
1289 $colsRegionCW = self::$dataRegionCols[$index];
1290 $rowsLengthMatrice = $rowsTotal - 2 * $rowsRegion; // Size of matrice data
1291 $colsLengthMatrice = $colsTotal - 2 * $colsRegion;
1292 $blocks = self::$interleavedBlocks[$index]; // Number of Reed Solomon blocks
1293 $errorBlocks = $solomonCWCount / $blocks;
1295 self::addPadCW($dataCodeWords, $dataCWCount, $totalDataCWCount); // Add codewords pads
1297 $g = self::calculSolFactorTable($errorBlocks); // Calculate correction coefficients
1299 self::addReedSolomonCW($solomonCWCount, $g, $totalDataCWCount, $dataCodeWords, $blocks); // Add Reed Solomon codewords
1301 $codeWordsBits = array(); // Calculte bits from codewords
1302 for ($i = 0; $i < $totalCWCount; $i++) {
1303 $codeWordsBits[$i] = self::getBits($dataCodeWords[$i]);
1306 $datamatrix = array_fill(0, $colsLengthMatrice, array());
1307 $assigned = array_fill(0, $colsLengthMatrice, array());
1309 // Add the bottom-right corner if needed
1310 if ((($rowsLengthMatrice * $colsLengthMatrice) % 8) == 4) {
1311 $datamatrix[$rowsLengthMatrice - 2][$colsLengthMatrice - 2] = 1;
1312 $datamatrix[$rowsLengthMatrice - 1][$colsLengthMatrice - 1] = 1;
1313 $datamatrix[$rowsLengthMatrice - 1][$colsLengthMatrice - 2] = 0;
1314 $datamatrix[$rowsLengthMatrice - 2][$colsLengthMatrice - 1] = 0;
1315 $assigned[$rowsLengthMatrice - 2][$colsLengthMatrice - 2] = 1;
1316 $assigned[$rowsLengthMatrice - 1][$colsLengthMatrice - 1] = 1;
1317 $assigned[$rowsLengthMatrice - 1][$colsLengthMatrice - 2] = 1;
1318 $assigned[$rowsLengthMatrice - 2][$colsLengthMatrice - 1] = 1;
1321 // Put the codewords into the matrix
1322 self::next(0, $rowsLengthMatrice, $colsLengthMatrice, $codeWordsBits, $datamatrix, $assigned);
1324 // Add the finder pattern
1325 $datamatrix = self::addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW);
1327 return $datamatrix;