Highway to PSR2
[openemr.git] / library / classes / php-barcode.php
blobcdac841278fb21d65cb1b01cfce47c732a10820c
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: http://barcode-coder.com/
14 * dual licence : http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
15 * http://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;
143 $i++) {
144 $d[$i] = $digit[$i];
147 return(array($d));
150 private static function digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit)
152 $lines = count($digit);
153 $columns = count($digit[0]);
154 $angle = deg2rad(-$angle);
155 $cos = cos($angle);
156 $sin = sin($angle);
158 self::_rotate($columns * $mw / 2, $lines * $mh / 2, $cos, $sin, $x, $y);
159 $xi -=$x;
160 $yi -=$y;
161 for ($y=0; $y<$lines; $y++) {
162 $x = -1;
163 while ($x <$columns) {
164 $x++;
165 if ($digit[$y][$x] == '1') {
166 $z = $x;
167 while (($z + 1 <$columns) && ($digit[$y][$z + 1] == '1')) {
168 $z++;
171 $x1 = $x * $mw;
172 $y1 = $y * $mh;
173 $x2 = ($z + 1) * $mw;
174 $y2 = ($y + 1) * $mh;
175 self::_rotate($x1, $y1, $cos, $sin, $xA, $yA);
176 self::_rotate($x2, $y1, $cos, $sin, $xB, $yB);
177 self::_rotate($x2, $y2, $cos, $sin, $xC, $yC);
178 self::_rotate($x1, $y2, $cos, $sin, $xD, $yD);
179 $fn(array(
180 $xA + $xi, $yA + $yi,
181 $xB + $xi, $yB + $yi,
182 $xC + $xi, $yC + $yi,
183 $xD + $xi, $yD + $yi
185 $x = $z + 1;
190 return self::result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin);
193 // GD barcode renderer
194 private static function digitToGDRenderer($gd, $color, $xi, $yi, $angle, $mw, $mh, $digit)
196 $fn = function ($points) use ($gd, $color) {
197 imagefilledpolygon($gd, $points, 4, $color);
199 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
201 // FPDF barcode renderer
202 private static function digitToFPDFRenderer($pdf, $color, $xi, $yi, $angle, $mw, $mh, $digit)
204 if (!is_array($color)) {
205 if (preg_match('`([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})`i', $color, $m)) {
206 $color = array(hexdec($m[1]),hexdec($m[2]),hexdec($m[3]));
207 } else {
208 $color = array(0,0,0);
212 $color = array_values($color);
213 $pdf->SetDrawColor($color[0], $color[1], $color[2]);
214 $pdf->SetFillColor($color[0], $color[1], $color[2]);
216 $fn = function ($points) use ($pdf) {
217 $op = 'f';
218 $h = $pdf->h;
219 $k = $pdf->k;
220 $points_string = '';
221 for ($i=0; $i < 8; $i+=2) {
222 $points_string .= sprintf('%.2F %.2F', $points[$i]*$k, ($h-$points[$i+1])*$k);
223 $points_string .= $i ? ' l ' : ' m ';
226 $pdf->_out($points_string . $op);
228 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
231 private static function result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin)
233 self::_rotate(0, 0, $cos, $sin, $x1, $y1);
234 self::_rotate($columns * $mw, 0, $cos, $sin, $x2, $y2);
235 self::_rotate($columns * $mw, $lines * $mh, $cos, $sin, $x3, $y3);
236 self::_rotate(0, $lines * $mh, $cos, $sin, $x4, $y4);
238 return array(
239 'width' => $columns * $mw,
240 'height'=> $lines * $mh,
241 'p1' => array(
242 'x' => $xi + $x1,
243 'y' => $yi + $y1
245 'p2' => array(
246 'x' => $xi + $x2,
247 'y' => $yi + $y2
249 'p3' => array(
250 'x' => $xi + $x3,
251 'y' => $yi + $y3
253 'p4' => array(
254 'x' => $xi + $x4,
255 'y' => $yi + $y4
260 private static function _rotate($x1, $y1, $cos, $sin, &$x, &$y)
262 $x = $x1 * $cos - $y1 * $sin;
263 $y = $x1 * $sin + $y1 * $cos;
266 public static function rotate($x1, $y1, $angle, &$x, &$y)
268 $angle = deg2rad(-$angle);
269 $cos = cos($angle);
270 $sin = sin($angle);
271 $x = $x1 * $cos - $y1 * $sin;
272 $y = $x1 * $sin + $y1 * $cos;
276 class BarcodeI25
278 static private $encoding = array('NNWWN', 'WNNNW', 'NWNNW', 'WWNNN', 'NNWNW', 'WNWNN', 'NWWNN', 'NNNWW', 'WNNWN','NWNWN');
280 public static function compute($code, $crc, $type)
282 if (! $crc) {
283 if (strlen($code) % 2) {
284 $code = '0' . $code;
286 } else {
287 if (($type == 'int25') && (strlen($code) % 2 == 0)) {
288 $code = '0' . $code;
291 $odd = true;
292 $sum = 0;
293 for ($i=strlen($code)-1; $i>-1; $i--) {
294 $v = intval($code[$i]);
295 $sum += $odd ? 3 * $v : $v;
296 $odd = ! $odd;
299 $code .= (string) ((10 - $sum % 10) % 10);
302 return($code);
305 public static function getDigit($code, $crc, $type)
307 $code = self::compute($code, $crc, $type);
308 if ($code == '') {
309 return($code);
312 $result = '';
314 if ($type == 'int25') { // Interleaved 2 of 5
315 // start
316 $result .= '1010';
318 // digits + CRC
319 $end = strlen($code) / 2;
320 for ($i=0; $i<$end; $i++) {
321 $c1 = $code[2*$i];
322 $c2 = $code[2*$i+1];
323 for ($j=0; $j<5; $j++) {
324 $result .= '1';
325 if (self::$encoding[$c1][$j] == 'W') {
326 $result .= '1';
329 $result .= '0';
330 if (self::$encoding[$c2][$j] == 'W') {
331 $result .= '0';
336 // stop
337 $result .= '1101';
338 } else if ($type == 'std25') {
339 // Standard 2 of 5 is a numeric-only barcode that has been in use a long time.
340 // 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.
341 // The code is self-checking and does not include a checksum.
343 // start
344 $result .= '11011010';
346 // digits + CRC
347 $end = strlen($code);
348 for ($i=0; $i<$end; $i++) {
349 $c = $code[$i];
350 for ($j=0; $j<5; $j++) {
351 $result .= '1';
352 if (self::$encoding[$c][$j] == 'W') {
353 $result .= '11';
356 $result .= '0';
360 // stop
361 $result .= '11010110';
364 return($result);
369 class BarcodeEAN
371 static private $encoding = array(
372 array('0001101', '0100111', '1110010'),
373 array('0011001', '0110011', '1100110'),
374 array('0010011', '0011011', '1101100'),
375 array('0111101', '0100001', '1000010'),
376 array('0100011', '0011101', '1011100'),
377 array('0110001', '0111001', '1001110'),
378 array('0101111', '0000101', '1010000'),
379 array('0111011', '0010001', '1000100'),
380 array('0110111', '0001001', '1001000'),
381 array('0001011', '0010111', '1110100')
384 static private $first = array('000000','001011','001101','001110','010011','011001','011100','010101','010110','011010');
386 public static function getDigit($code, $type)
388 // Check len (12 for ean13, 7 for ean8)
389 $len = $type == 'ean8' ? 7 : 12;
390 $code = substr($code, 0, $len);
391 if (!preg_match('`[0-9]{'.$len.'}`', $code)) {
392 return('');
395 // get checksum
396 $code = self::compute($code, $type);
398 // process analyse
399 $result = '101'; // start
401 if ($type == 'ean8') {
402 // process left part
403 for ($i=0; $i<4; $i++) {
404 $result .= self::$encoding[intval($code[$i])][0];
407 // center guard bars
408 $result .= '01010';
410 // process right part
411 for ($i=4; $i<8; $i++) {
412 $result .= self::$encoding[intval($code[$i])][2];
414 } else { // ean13
415 // extract first digit and get sequence
416 $seq = self::$first[ intval($code[0]) ];
418 // process left part
419 for ($i=1; $i<7; $i++) {
420 $result .= self::$encoding[intval($code[$i])][ intval($seq[$i-1]) ];
423 // center guard bars
424 $result .= '01010';
426 // process right part
427 for ($i=7; $i<13; $i++) {
428 $result .= self::$encoding[intval($code[$i])][ 2 ];
430 } // ean13
432 $result .= '101'; // stop
433 return($result);
436 public static function compute($code, $type)
438 $len = $type == 'ean13' ? 12 : 7;
439 $code = substr($code, 0, $len);
440 if (!preg_match('`[0-9]{'.$len.'}`', $code)) {
441 return('');
444 $sum = 0;
445 $odd = true;
446 for ($i=$len-1; $i>-1; $i--) {
447 $sum += ($odd ? 3 : 1) * intval($code[$i]);
448 $odd = ! $odd;
451 return($code . ( (string) ((10 - $sum % 10) % 10)));
455 class BarcodeUPC
458 public static function getDigit($code)
460 if (strlen($code) < 12) {
461 $code = '0' . $code;
464 return BarcodeEAN::getDigit($code, 'ean13');
467 public static function compute($code)
469 if (strlen($code) < 12) {
470 $code = '0' . $code;
473 return substr(BarcodeEAN::compute($code, 'ean13'), 1);
477 class BarcodeMSI
479 static private $encoding = array(
480 '100100100100', '100100100110', '100100110100', '100100110110',
481 '100110100100', '100110100110', '100110110100', '100110110110',
482 '110100100100', '110100100110');
484 public static function compute($code, $crc)
486 if (is_array($crc)) {
487 if ($crc['crc1'] == 'mod10') {
488 $code = self::computeMod10($code);
489 } else if ($crc['crc1'] == 'mod11') {
490 $code = self::computeMod11($code);
493 if ($crc['crc2'] == 'mod10') {
494 $code = self::computeMod10($code);
495 } else if ($crc['crc2'] == 'mod11') {
496 $code = self::computeMod11($code);
498 } else if ($crc) {
499 $code = self::computeMod10($code);
502 return($code);
505 private static function computeMod10($code)
507 $len = strlen($code);
508 $toPart1 = $len % 2;
509 $n1 = 0;
510 $sum = 0;
511 for ($i=0; $i<$len; $i++) {
512 if ($toPart1) {
513 $n1 = 10 * $n1 + intval($code[$i]);
514 } else {
515 $sum += intval($code[$i]);
518 $toPart1 = ! $toPart1;
521 $s1 = (string) (2 * $n1);
522 $len = strlen($s1);
523 for ($i=0; $i<$len; $i++) {
524 $sum += intval($s1[$i]);
527 return($code . ( (string) (10 - $sum % 10) % 10));
530 private static function computeMod11($code)
532 $sum = 0;
533 $weight = 2;
534 for ($i=strlen($code)-1; $i>-1; $i--) {
535 $sum += $weight * intval($code[$i]);
536 $weight = $weight == 7 ? 2 : $weight + 1;
539 return($code . ( (string) (11 - $sum % 11) % 11) );
542 public static function getDigit($code, $crc)
544 if (preg_match('`[^0-9]`', $code)) {
545 return '';
548 $index = 0;
549 $result = '';
551 $code = self::compute($code, false);
553 // start
554 $result = '110';
556 // digits
557 $len = strlen($code);
558 for ($i=0; $i<$len; $i++) {
559 $result .= self::$encoding[ intval($code[$i]) ];
562 // stop
563 $result .= '1001';
565 return($result);
569 class Barcode11
571 static private $encoding = array(
572 '101011', '1101011', '1001011', '1100101',
573 '1011011', '1101101', '1001101', '1010011',
574 '1101001', '110101', '101101');
576 public static function getDigit($code)
578 if (preg_match('`[^0-9\-]`', $code)) {
579 return '';
582 $result = '';
583 $intercharacter = '0';
585 // start
586 $result = '1011001' . $intercharacter;
588 // digits
589 $len = strlen($code);
590 for ($i=0; $i<$len; $i++) {
591 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
592 $result .= self::$encoding[ $index ] . $intercharacter;
595 // checksum
596 $weightC = 0;
597 $weightSumC = 0;
598 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
599 $weightSumK = 0;
600 for ($i=$len-1; $i>-1; $i--) {
601 $weightC = $weightC == 10 ? 1 : $weightC + 1;
602 $weightK = $weightK == 10 ? 1 : $weightK + 1;
604 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
606 $weightSumC += $weightC * $index;
607 $weightSumK += $weightK * $index;
610 $c = $weightSumC % 11;
611 $weightSumK += $c;
612 $k = $weightSumK % 11;
614 $result .= self::$encoding[$c] . $intercharacter;
616 if ($len >= 10) {
617 $result .= self::$encoding[$k] . $intercharacter;
620 // stop
621 $result .= '1011001';
623 return($result);
627 class Barcode39
629 static private $encoding = array(
630 '101001101101', '110100101011', '101100101011', '110110010101',
631 '101001101011', '110100110101', '101100110101', '101001011011',
632 '110100101101', '101100101101', '110101001011', '101101001011',
633 '110110100101', '101011001011', '110101100101', '101101100101',
634 '101010011011', '110101001101', '101101001101', '101011001101',
635 '110101010011', '101101010011', '110110101001', '101011010011',
636 '110101101001', '101101101001', '101010110011', '110101011001',
637 '101101011001', '101011011001', '110010101011', '100110101011',
638 '110011010101', '100101101011', '110010110101', '100110110101',
639 '100101011011', '110010101101', '100110101101', '100100100101',
640 '100100101001', '100101001001', '101001001001', '100101101101');
641 public static function getDigit($code)
643 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*';
644 $result = '';
645 $intercharacter = '0';
647 if (strpos($code, '*') !== false) {
648 return('');
651 // Add Start and Stop charactere : *
652 $code = strtoupper('*' . $code . '*');
654 $len = strlen($code);
655 for ($i=0; $i<$len; $i++) {
656 $index = strpos($table, $code[$i]);
657 if ($index === false) {
658 return('');
661 if ($i > 0) {
662 $result .= $intercharacter;
665 $result .= self::$encoding[ $index ];
668 return($result);
672 class Barcode93
674 static private $encoding = array(
675 '100010100', '101001000', '101000100', '101000010',
676 '100101000', '100100100', '100100010', '101010000',
677 '100010010', '100001010', '110101000', '110100100',
678 '110100010', '110010100', '110010010', '110001010',
679 '101101000', '101100100', '101100010', '100110100',
680 '100011010', '101011000', '101001100', '101000110',
681 '100101100', '100010110', '110110100', '110110010',
682 '110101100', '110100110', '110010110', '110011010',
683 '101101100', '101100110', '100110110', '100111010',
684 '100101110', '111010100', '111010010', '111001010',
685 '101101110', '101110110', '110101110', '100100110',
686 '111011010', '111010110', '100110010', '101011110');
688 public static function getDigit($code, $crc)
690 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%____*'; // _ => ($), (%), (/) et (+)
691 $result = '';
693 if (strpos($code, '*') !== false) {
694 return('');
697 $code = strtoupper($code);
699 // start : *
700 $result .= self::$encoding[47];
702 // digits
703 $len = strlen($code);
704 for ($i=0; $i<$len; $i++) {
705 $c = $code[$i];
706 $index = strpos($table, $c);
707 if (($c == '_') || ($index === false)) {
708 return('');
711 $result .= self::$encoding[ $index ];
714 // checksum
715 if ($crc) {
716 $weightC = 0;
717 $weightSumC = 0;
718 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
719 $weightSumK = 0;
720 for ($i=$len-1; $i>-1; $i--) {
721 $weightC = $weightC == 20 ? 1 : $weightC + 1;
722 $weightK = $weightK == 15 ? 1 : $weightK + 1;
724 $index = strpos($table, $code[$i]);
726 $weightSumC += $weightC * $index;
727 $weightSumK += $weightK * $index;
730 $c = $weightSumC % 47;
731 $weightSumK += $c;
732 $k = $weightSumK % 47;
734 $result .= self::$encoding[$c];
735 $result .= self::$encoding[$k];
738 // stop : *
739 $result .= self::$encoding[47];
741 // Terminaison bar
742 $result .= '1';
743 return($result);
747 class Barcode128
749 static private $encoding = array(
750 '11011001100', '11001101100', '11001100110', '10010011000',
751 '10010001100', '10001001100', '10011001000', '10011000100',
752 '10001100100', '11001001000', '11001000100', '11000100100',
753 '10110011100', '10011011100', '10011001110', '10111001100',
754 '10011101100', '10011100110', '11001110010', '11001011100',
755 '11001001110', '11011100100', '11001110100', '11101101110',
756 '11101001100', '11100101100', '11100100110', '11101100100',
757 '11100110100', '11100110010', '11011011000', '11011000110',
758 '11000110110', '10100011000', '10001011000', '10001000110',
759 '10110001000', '10001101000', '10001100010', '11010001000',
760 '11000101000', '11000100010', '10110111000', '10110001110',
761 '10001101110', '10111011000', '10111000110', '10001110110',
762 '11101110110', '11010001110', '11000101110', '11011101000',
763 '11011100010', '11011101110', '11101011000', '11101000110',
764 '11100010110', '11101101000', '11101100010', '11100011010',
765 '11101111010', '11001000010', '11110001010', '10100110000',
766 '10100001100', '10010110000', '10010000110', '10000101100',
767 '10000100110', '10110010000', '10110000100', '10011010000',
768 '10011000010', '10000110100', '10000110010', '11000010010',
769 '11001010000', '11110111010', '11000010100', '10001111010',
770 '10100111100', '10010111100', '10010011110', '10111100100',
771 '10011110100', '10011110010', '11110100100', '11110010100',
772 '11110010010', '11011011110', '11011110110', '11110110110',
773 '10101111000', '10100011110', '10001011110', '10111101000',
774 '10111100010', '11110101000', '11110100010', '10111011110',
775 '10111101110', '11101011110', '11110101110', '11010000100',
776 '11010010000', '11010011100', '11000111010');
777 public static function getDigit($code)
779 $tableB = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
780 $result = "";
781 $sum = 0;
782 $isum = 0;
783 $i = 0;
784 $j = 0;
785 $value = 0;
787 // check each characters
788 $len = strlen($code);
789 for ($i=0; $i<$len; $i++) {
790 if (strpos($tableB, $code[$i]) === false) {
791 return("");
795 // check firsts characters : start with C table only if enought numeric
796 $tableCActivated = $len> 1;
797 $c = '';
798 for ($i=0; $i<3 && $i<$len; $i++) {
799 $tableCActivated &= preg_match('`[0-9]`', $code[$i]);
802 $sum = $tableCActivated ? 105 : 104;
804 // start : [105] : C table or [104] : B table
805 $result = self::$encoding[ $sum ];
807 $i = 0;
808 while ($i < $len) {
809 if (! $tableCActivated) {
810 $j = 0;
811 // check next character to activate C table if interresting
812 while (($i + $j < $len) && preg_match('`[0-9]`', $code[$i+$j])) {
813 $j++;
816 // 6 min everywhere or 4 mini at the end
817 $tableCActivated = ($j > 5) || (($i + $j - 1 == $len) && ($j > 3));
819 if ($tableCActivated) {
820 $result .= self::$encoding[ 99 ]; // C table
821 $sum += ++$isum * 99;
824 // 2 min for table C so need table B
825 } 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
826 $tableCActivated = false;
827 $result .= self::$encoding[ 100 ]; // B table
828 $sum += ++$isum * 100;
831 if ($tableCActivated) {
832 $value = intval(substr($code, $i, 2)); // Add two characters (numeric)
833 $i += 2;
834 } else {
835 $value = strpos($tableB, $code[$i]); // Add one character
836 $i++;
839 $result .= self::$encoding[ $value ];
840 $sum += ++$isum * $value;
843 // Add CRC
844 $result .= self::$encoding[ $sum % 103 ];
846 // Stop
847 $result .= self::$encoding[ 106 ];
849 // Termination bar
850 $result .= '11';
852 return($result);
856 class BarcodeCodabar
858 static private $encoding = array(
859 '101010011', '101011001', '101001011', '110010101',
860 '101101001', '110101001', '100101011', '100101101',
861 '100110101', '110100101', '101001101', '101100101',
862 '1101011011', '1101101011', '1101101101', '1011011011',
863 '1011001001', '1010010011', '1001001011', '1010011001');
865 public static function getDigit($code)
867 $table = '0123456789-$:/.+';
868 $result = '';
869 $intercharacter = '0';
871 // add start : A->D : arbitrary choose A
872 $result .= self::$encoding[16] . $intercharacter;
874 $len = strlen($code);
875 for ($i=0; $i<$len; $i++) {
876 $index = strpos($table, $code[$i]);
877 if ($index === false) {
878 return('');
881 $result .= self::$encoding[ $index ] . $intercharacter;
884 // add stop : A->D : arbitrary choose A
885 $result .= self::$encoding[16];
886 return($result);
890 class BarcodeDatamatrix
892 static private $lengthRows = array(
893 10, 12, 14, 16, 18, 20, 22, 24, 26, // 24 squares et 6 rectangular
894 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
895 8, 8, 12, 12, 16, 16);
896 static private $lengthCols = array(
897 10, 12, 14, 16, 18, 20, 22, 24, 26, // Number of columns for the entire datamatrix
898 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
899 18, 32, 26, 36, 36, 48);
900 static private $dataCWCount = array(
901 3, 5, 8, 12, 18, 22, 30, 36, // Number of data codewords for the datamatrix
902 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816, 1050,
903 1304, 1558, 5, 10, 16, 22, 32, 49);
904 static private $solomonCWCount = array(
905 5, 7, 10, 12, 14, 18, 20, 24, 28, // Number of Reed-Solomon codewords for the datamatrix
906 36, 42, 48, 56, 68, 84, 112, 144, 192, 224, 272, 336, 408, 496, 620,
907 7, 11, 14, 18, 24, 28);
908 static private $dataRegionRows = array(
909 8, 10, 12, 14, 16, 18, 20, 22, // Number of rows per region
910 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
911 6, 6, 10, 10, 14, 14);
912 static private $dataRegionCols = array(
913 8, 10, 12, 14, 16, 18, 20, 22, // Number of columns per region
914 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
915 16, 14, 24, 16, 16, 22);
916 static private $regionRows = array(
917 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per row
918 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
919 1, 1, 1, 1, 1, 1);
920 static private $regionCols = array(
921 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per column
922 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
923 1, 2, 1, 2, 2, 2);
924 static private $interleavedBlocks = array(
925 1, 1, 1, 1, 1, 1, 1, 1, // Number of blocks
926 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 6, 6, 8, 8,
927 1, 1, 1, 1, 1, 1);
928 static private $logTab = array(
929 -255, 255, 1, 240, 2, 225, 241, 53, 3, // Table of log for the Galois field
930 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106, 134, 28,
931 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115,
932 103, 228, 78, 107, 125, 135, 8, 29, 162, 244, 186, 141, 180, 45, 99,
933 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76, 220, 217, 197,
934 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171,
935 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187,
936 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, 57, 147,
937 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7,
938 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
939 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194,
940 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127,
941 247, 146, 66, 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73,
942 164, 144, 85, 170, 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82,
943 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112,
944 232, 21, 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149,
945 129, 19, 155, 59, 249, 70, 214, 250, 168, 71, 201, 156, 64, 60, 237,
946 130, 111, 20, 93, 122, 177, 150);
947 static private $aLogTab = array(
948 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, // Table of aLog for the Galois field
949 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219, 155, 27, 54,
950 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36,
951 72, 144, 13, 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56,
952 112, 224, 237, 247, 195, 171, 123, 246, 193, 175, 115, 230, 225, 239,
953 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190,
954 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106,
955 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, 217, 159, 19, 38, 76,
956 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223,
957 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113,
958 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, 214, 129,
959 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, 127,
960 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
961 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161,
962 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132,
963 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248,
964 221, 151, 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75,
965 150, 1);
966 private static function champGaloisMult($a, $b)
968 // MULTIPLICATION IN GALOIS FIELD GF(2^8)
969 if (!$a || !$b) {
970 return 0;
973 return self::$aLogTab[(self::$logTab[$a] + self::$logTab[$b]) % 255];
975 private static function champGaloisDoub($a, $b)
977 // THE OPERATION a * 2^b IN GALOIS FIELD GF(2^8)
978 if (!$a) {
979 return 0;
982 if (!$b) {
983 return $a;
986 return self::$aLogTab[(self::$logTab[$a] + $b) % 255];
988 private static function champGaloisSum($a, $b)
990 // SUM IN GALOIS FIELD GF(2^8)
991 return $a ^ $b;
993 private static function selectIndex($dataCodeWordsCount, $rectangular)
995 // CHOOSE THE GOOD INDEX FOR TABLES
996 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>1558) && !$rectangular) {
997 return -1;
1000 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>49) && $rectangular) {
1001 return -1;
1004 $n = $rectangular ? 24 : 0;
1006 while (self::$dataCWCount[$n] < $dataCodeWordsCount) {
1007 $n++;
1010 return $n;
1012 private static function encodeDataCodeWordsASCII($text)
1014 $dataCodeWords = array();
1015 $n = 0;
1016 $len = strlen($text);
1017 for ($i=0; $i<$len; $i++) {
1018 $c = ord($text[$i]);
1019 if ($c > 127) {
1020 $dataCodeWords[$n] = 235;
1021 $c -= 127;
1022 $n++;
1023 } else if (($c>=48 && $c<=57) && ($i+1<$len) && (preg_match('`[0-9]`', $text[$i+1]))) {
1024 $c = (($c - 48) * 10) + intval($text[$i+1]);
1025 $c += 130;
1026 $i++;
1027 } else {
1028 $c++;
1031 $dataCodeWords[$n] = $c;
1032 $n++;
1035 return $dataCodeWords;
1037 private static function addPadCW(&$tab, $from, $to)
1039 if ($from >= $to) {
1040 return ;
1043 $tab[$from] = 129;
1044 for ($i=$from+1; $i<$to; $i++) {
1045 $r = ((149 * ($i+1)) % 253) + 1;
1046 $tab[$i] = (129 + $r) % 254;
1049 private static function calculSolFactorTable($solomonCWCount)
1051 // CALCULATE THE REED SOLOMON FACTORS
1052 $g = array_fill(0, $solomonCWCount+1, 1);
1053 for ($i = 1; $i <= $solomonCWCount; $i++) {
1054 for ($j = $i - 1; $j >= 0; $j--) {
1055 $g[$j] = self::champGaloisDoub($g[$j], $i);
1056 if ($j > 0) {
1057 $g[$j] = self::champGaloisSum($g[$j], $g[$j-1]);
1062 return $g;
1064 private static function addReedSolomonCW($nSolomonCW, $coeffTab, $nDataCW, &$dataTab, $blocks)
1066 // Add the Reed Solomon codewords
1067 $errorBlocks = $nSolomonCW / $blocks;
1068 $correctionCW = array();
1070 for ($k = 0; $k < $blocks; $k++) {
1071 for ($i=0; $i < $errorBlocks;
1072 $i++) {
1073 $correctionCW[$i] = 0;
1076 for ($i=$k; $i<$nDataCW; $i+=$blocks) {
1077 $temp = self::champGaloisSum($dataTab[$i], $correctionCW[$errorBlocks-1]);
1078 for ($j=$errorBlocks-1; $j>=0; $j--) {
1079 if (!$temp) {
1080 $correctionCW[$j] = 0;
1081 } else {
1082 $correctionCW[$j] = self::champGaloisMult($temp, $coeffTab[$j]);
1085 if ($j>0) {
1086 $correctionCW[$j] = self::champGaloisSum($correctionCW[$j-1], $correctionCW[$j]);
1091 // Renversement des blocs calcules
1092 $j = $nDataCW + $k;
1093 for ($i=$errorBlocks-1; $i>=0; $i--) {
1094 $dataTab[$j] = $correctionCW[$i];
1095 $j=$j+$blocks;
1099 return $dataTab;
1101 private static function getBits($entier)
1103 // Transform integer to tab of bits
1104 $bits = array();
1105 for ($i=0; $i<8; $i++) {
1106 $bits[$i] = $entier & (128 >> $i) ? 1 : 0;
1109 return $bits;
1111 private static function next($etape, $totalRows, $totalCols, $codeWordsBits, &$datamatrix, &$assigned)
1113 // Place codewords into the matrix
1114 $chr = 0; // Place of the 8st bit from the first character to [4][0]
1115 $row = 4;
1116 $col = 0;
1118 do {
1119 // Check for a special case of corner
1120 if (($row == $totalRows) && ($col == 0)) {
1121 self::patternShapeSpecial1($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1122 $chr++;
1123 } else if (($etape<3) && ($row == $totalRows-2) && ($col == 0) && ($totalCols%4 != 0)) {
1124 self::patternShapeSpecial2($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1125 $chr++;
1126 } else if (($row == $totalRows-2) && ($col == 0) && ($totalCols%8 == 4)) {
1127 self::patternShapeSpecial3($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1128 $chr++;
1129 } else if (($row == $totalRows+4) && ($col == 2) && ($totalCols%8 == 0)) {
1130 self::patternShapeSpecial4($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
1131 $chr++;
1134 // Go up and right in the datamatrix
1135 do {
1136 if (($row < $totalRows) && ($col >= 0) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)) {
1137 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1138 $chr++;
1141 $row -= 2;
1142 $col += 2;
1143 } while (($row >= 0) && ($col < $totalCols));
1144 $row += 1;
1145 $col += 3;
1147 // Go down and left in the datamatrix
1148 do {
1149 if (($row >= 0) && ($col < $totalCols) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)) {
1150 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
1151 $chr++;
1154 $row += 2;
1155 $col -= 2;
1156 } while (($row < $totalRows) && ($col >=0));
1157 $row += 3;
1158 $col += 1;
1159 } while (($row < $totalRows) || ($col < $totalCols));
1161 private static function patternShapeStandard(&$datamatrix, &$assigned, $bits, $row, $col, $totalRows, $totalCols)
1163 // Place bits in the matrix (standard or special case)
1164 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $row-2, $col-2, $totalRows, $totalCols);
1165 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $row-2, $col-1, $totalRows, $totalCols);
1166 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $row-1, $col-2, $totalRows, $totalCols);
1167 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], $row-1, $col-1, $totalRows, $totalCols);
1168 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], $row-1, $col, $totalRows, $totalCols);
1169 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], $row, $col-2, $totalRows, $totalCols);
1170 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], $row, $col-1, $totalRows, $totalCols);
1171 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], $row, $col, $totalRows, $totalCols);
1173 private static function patternShapeSpecial1(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1175 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1176 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, 1, $totalRows, $totalCols);
1177 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 2, $totalRows, $totalCols);
1178 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1179 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1180 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1181 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1182 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1184 private static function patternShapeSpecial2(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1186 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1187 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1188 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1189 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-4, $totalRows, $totalCols);
1190 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-3, $totalRows, $totalCols);
1191 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 0, $totalCols-2, $totalRows, $totalCols);
1192 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 0, $totalCols-1, $totalRows, $totalCols);
1193 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1195 private static function patternShapeSpecial3(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1197 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1198 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1199 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1200 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1201 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1202 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1203 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1204 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1206 private static function patternShapeSpecial4(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols)
1208 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1209 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, $totalCols-1, $totalRows, $totalCols);
1210 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], 0, $totalCols-3, $totalRows, $totalCols);
1211 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1212 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1213 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-3, $totalRows, $totalCols);
1214 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 1, $totalCols-2, $totalRows, $totalCols);
1215 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1217 private static function placeBitInDatamatrix(&$datamatrix, &$assigned, $bit, $row, $col, $totalRows, $totalCols)
1219 // Put a bit into the matrix
1220 if ($row < 0) {
1221 $row += $totalRows;
1222 $col += 4 - (($totalRows+4)%8);
1225 if ($col < 0) {
1226 $col += $totalCols;
1227 $row += 4 - (($totalCols+4)%8);
1230 if (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1) {
1231 $datamatrix[$row][$col] = $bit;
1232 $assigned[$row][$col] = 1;
1235 private static function addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW)
1237 // Add the finder pattern
1238 $totalRowsCW = ($rowsRegionCW+2) * $rowsRegion;
1239 $totalColsCW = ($colsRegionCW+2) * $colsRegion;
1241 $datamatrixTemp = array();
1242 $datamatrixTemp[0] = array_fill(0, $totalColsCW+2, 0);
1244 for ($i=0; $i<$totalRowsCW; $i++) {
1245 $datamatrixTemp[$i+1] = array();
1246 $datamatrixTemp[$i+1][0] = 0;
1247 $datamatrixTemp[$i+1][$totalColsCW+1] = 0;
1248 for ($j=0; $j<$totalColsCW; $j++) {
1249 if ($i%($rowsRegionCW+2) == 0) {
1250 if ($j%2 == 0) {
1251 $datamatrixTemp[$i+1][$j+1] = 1;
1252 } else {
1253 $datamatrixTemp[$i+1][$j+1] = 0;
1255 } else if ($i%($rowsRegionCW+2) == $rowsRegionCW+1) {
1256 $datamatrixTemp[$i+1][$j+1] = 1;
1257 } else if ($j%($colsRegionCW+2) == $colsRegionCW+1) {
1258 if ($i%2 == 0) {
1259 $datamatrixTemp[$i+1][$j+1] = 0;
1260 } else {
1261 $datamatrixTemp[$i+1][$j+1] = 1;
1263 } else if ($j%($colsRegionCW+2) == 0) {
1264 $datamatrixTemp[$i+1][$j+1] = 1;
1265 } else {
1266 $datamatrixTemp[$i+1][$j+1] = 0;
1267 $datamatrixTemp[$i+1][$j+1] = $datamatrix[$i-1-(2*(floor($i/($rowsRegionCW+2))))][$j-1-(2*(floor($j/($colsRegionCW+2))))]; // todo : parseInt => ?
1272 $datamatrixTemp[$totalRowsCW+1] = array();
1273 for ($j=0; $j<$totalColsCW+2; $j++) {
1274 $datamatrixTemp[$totalRowsCW+1][$j] = 0;
1277 return $datamatrixTemp;
1279 public static function getDigit($text, $rectangular)
1281 $dataCodeWords = self::encodeDataCodeWordsASCII($text); // Code the text in the ASCII mode
1282 $dataCWCount = count($dataCodeWords);
1283 $index = self::selectIndex($dataCWCount, $rectangular); // Select the index for the data tables
1284 $totalDataCWCount = self::$dataCWCount[$index]; // Number of data CW
1285 $solomonCWCount = self::$solomonCWCount[$index]; // Number of Reed Solomon CW
1286 $totalCWCount = $totalDataCWCount + $solomonCWCount; // Number of CW
1287 $rowsTotal = self::$lengthRows[$index]; // Size of symbol
1288 $colsTotal = self::$lengthCols[$index];
1289 $rowsRegion = self::$regionRows[$index]; // Number of region
1290 $colsRegion = self::$regionCols[$index];
1291 $rowsRegionCW = self::$dataRegionRows[$index];
1292 $colsRegionCW = self::$dataRegionCols[$index];
1293 $rowsLengthMatrice = $rowsTotal-2*$rowsRegion; // Size of matrice data
1294 $colsLengthMatrice = $colsTotal-2*$colsRegion;
1295 $blocks = self::$interleavedBlocks[$index]; // Number of Reed Solomon blocks
1296 $errorBlocks = $solomonCWCount / $blocks;
1298 self::addPadCW($dataCodeWords, $dataCWCount, $totalDataCWCount); // Add codewords pads
1300 $g = self::calculSolFactorTable($errorBlocks); // Calculate correction coefficients
1302 self::addReedSolomonCW($solomonCWCount, $g, $totalDataCWCount, $dataCodeWords, $blocks); // Add Reed Solomon codewords
1304 $codeWordsBits = array(); // Calculte bits from codewords
1305 for ($i=0; $i<$totalCWCount; $i++) {
1306 $codeWordsBits[$i] = self::getBits($dataCodeWords[$i]);
1309 $datamatrix = array_fill(0, $colsLengthMatrice, array());
1310 $assigned = array_fill(0, $colsLengthMatrice, array());
1312 // Add the bottom-right corner if needed
1313 if ((($rowsLengthMatrice * $colsLengthMatrice) % 8) == 4) {
1314 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1315 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1316 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 0;
1317 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 0;
1318 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1319 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1320 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 1;
1321 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 1;
1324 // Put the codewords into the matrix
1325 self::next(0, $rowsLengthMatrice, $colsLengthMatrice, $codeWordsBits, $datamatrix, $assigned);
1327 // Add the finder pattern
1328 $datamatrix = self::addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW);
1330 return $datamatrix;