added datepicker to immunization gui
[openemr.git] / library / classes / php-barcode.php
blob8e6760d5360f072535251c1a6f8eb6b1d4623f25
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 {
30 static public function gd($res, $color, $x, $y, $angle, $type, $datas, $width = null, $height = null){
31 return self::_draw(__FUNCTION__, $res, $color, $x, $y, $angle, $type, $datas, $width, $height);
34 static public function fpdf($res, $color, $x, $y, $angle, $type, $datas, $width = null, $height = null){
35 return self::_draw(__FUNCTION__, $res, $color, $x, $y, $angle, $type, $datas, $width, $height);
38 static private function _draw($call, $res, $color, $x, $y, $angle, $type, $datas, $width, $height){
39 $digit = '';
40 $hri = '';
41 $code = '';
42 $crc = true;
43 $rect = false;
44 $b2d = false;
46 if (is_array($datas)){
47 foreach(array('code' => '', 'crc' => true, 'rect' => false) as $v => $def){
48 $$v = isset($datas[$v]) ? $datas[$v] : $def;
50 $code = $code;
51 } else {
52 $code = $datas;
54 if ($code == '') return false;
55 $code = (string) $code;
57 $type = strtolower($type);
59 switch($type){
60 case 'std25':
61 case 'int25':
62 $digit = BarcodeI25::getDigit($code, $crc, $type);
63 $hri = BarcodeI25::compute($code, $crc, $type);
64 break;
65 case 'ean8':
66 case 'ean13':
67 $digit = BarcodeEAN::getDigit($code, $type);
68 $hri = BarcodeEAN::compute($code, $type);
69 break;
70 case 'upc':
71 $digit = BarcodeUPC::getDigit($code);
72 $hri = BarcodeUPC::compute($code);
73 break;
74 case 'code11':
75 $digit = Barcode11::getDigit($code);
76 $hri = $code;
77 break;
78 case 'code39':
79 $digit = Barcode39::getDigit($code);
80 $hri = $code;
81 break;
82 case 'code93':
83 $digit = Barcode93::getDigit($code, $crc);
84 $hri = $code;
85 break;
86 case 'code128':
87 $digit = Barcode128::getDigit($code);
88 $hri = $code;
89 break;
90 case 'codabar':
91 $digit = BarcodeCodabar::getDigit($code);
92 $hri = $code;
93 break;
94 case 'msi':
95 $digit = BarcodeMSI::getDigit($code, $crc);
96 $hri = BarcodeMSI::compute($code, $crc);
97 break;
98 case 'datamatrix':
99 $digit = BarcodeDatamatrix::getDigit($code, $rect);
100 $hri = $code;
101 $b2d = true;
102 break;
105 if ($digit == '') return false;
107 if ( $b2d ){
108 $width = is_null($width) ? 5 : $width;
109 $height = $width;
110 } else {
111 $width = is_null($width) ? 1 : $width;
112 $height = is_null($height) ? 50 : $height;
113 $digit = self::bitStringTo2DArray($digit);
116 if ( $call == 'gd' ){
117 $result = self::digitToGDRenderer($res, $color, $x, $y, $angle, $width, $height, $digit);
118 } else if ( $call == 'fpdf' ){
119 $result = self::digitToFPDFRenderer($res, $color, $x, $y, $angle, $width, $height, $digit);
122 $result['hri'] = $hri;
123 return $result;
126 // convert a bit string to an array of array of bit char
127 private static function bitStringTo2DArray( $digit ){
128 $d = array();
129 $len = strlen($digit);
130 for($i=0; $i<$len; $i++) $d[$i] = $digit[$i];
131 return(array($d));
134 private static function digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit){
135 $lines = count($digit);
136 $columns = count($digit[0]);
137 $angle = deg2rad(-$angle);
138 $cos = cos($angle);
139 $sin = sin($angle);
141 self::_rotate($columns * $mw / 2, $lines * $mh / 2, $cos, $sin , $x, $y);
142 $xi -=$x;
143 $yi -=$y;
144 for($y=0; $y<$lines; $y++){
145 $x = -1;
146 while($x <$columns) {
147 $x++;
148 if ($digit[$y][$x] == '1') {
149 $z = $x;
150 while(($z + 1 <$columns) && ($digit[$y][$z + 1] == '1')) {
151 $z++;
153 $x1 = $x * $mw;
154 $y1 = $y * $mh;
155 $x2 = ($z + 1) * $mw;
156 $y2 = ($y + 1) * $mh;
157 self::_rotate($x1, $y1, $cos, $sin, $xA, $yA);
158 self::_rotate($x2, $y1, $cos, $sin, $xB, $yB);
159 self::_rotate($x2, $y2, $cos, $sin, $xC, $yC);
160 self::_rotate($x1, $y2, $cos, $sin, $xD, $yD);
161 $fn(array(
162 $xA + $xi, $yA + $yi,
163 $xB + $xi, $yB + $yi,
164 $xC + $xi, $yC + $yi,
165 $xD + $xi, $yD + $yi
167 $x = $z + 1;
171 return self::result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin);
174 // GD barcode renderer
175 private static function digitToGDRenderer($gd, $color, $xi, $yi, $angle, $mw, $mh, $digit){
176 $fn = function($points) use ($gd, $color) {
177 imagefilledpolygon($gd, $points, 4, $color);
179 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
181 // FPDF barcode renderer
182 private static function digitToFPDFRenderer($pdf, $color, $xi, $yi, $angle, $mw, $mh, $digit){
183 if (!is_array($color)){
184 if (preg_match('`([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})`i', $color, $m)){
185 $color = array(hexdec($m[1]),hexdec($m[2]),hexdec($m[3]));
186 } else {
187 $color = array(0,0,0);
190 $color = array_values($color);
191 $pdf->SetDrawColor($color[0],$color[1],$color[2]);
192 $pdf->SetFillColor($color[0],$color[1],$color[2]);
194 $fn = function($points) use ($pdf) {
195 $op = 'f';
196 $h = $pdf->h;
197 $k = $pdf->k;
198 $points_string = '';
199 for($i=0; $i < 8; $i+=2){
200 $points_string .= sprintf('%.2F %.2F', $points[$i]*$k, ($h-$points[$i+1])*$k);
201 $points_string .= $i ? ' l ' : ' m ';
203 $pdf->_out($points_string . $op);
205 return self::digitToRenderer($fn, $xi, $yi, $angle, $mw, $mh, $digit);
208 static private function result($xi, $yi, $columns, $lines, $mw, $mh, $cos, $sin){
209 self::_rotate(0, 0, $cos, $sin , $x1, $y1);
210 self::_rotate($columns * $mw, 0, $cos, $sin , $x2, $y2);
211 self::_rotate($columns * $mw, $lines * $mh, $cos, $sin , $x3, $y3);
212 self::_rotate(0, $lines * $mh, $cos, $sin , $x4, $y4);
214 return array(
215 'width' => $columns * $mw,
216 'height'=> $lines * $mh,
217 'p1' => array(
218 'x' => $xi + $x1,
219 'y' => $yi + $y1
221 'p2' => array(
222 'x' => $xi + $x2,
223 'y' => $yi + $y2
225 'p3' => array(
226 'x' => $xi + $x3,
227 'y' => $yi + $y3
229 'p4' => array(
230 'x' => $xi + $x4,
231 'y' => $yi + $y4
236 static private function _rotate($x1, $y1, $cos, $sin , &$x, &$y){
237 $x = $x1 * $cos - $y1 * $sin;
238 $y = $x1 * $sin + $y1 * $cos;
241 static public function rotate($x1, $y1, $angle , &$x, &$y){
242 $angle = deg2rad(-$angle);
243 $cos = cos($angle);
244 $sin = sin($angle);
245 $x = $x1 * $cos - $y1 * $sin;
246 $y = $x1 * $sin + $y1 * $cos;
250 class BarcodeI25 {
251 static private $encoding = array('NNWWN', 'WNNNW', 'NWNNW', 'WWNNN', 'NNWNW', 'WNWNN', 'NWWNN', 'NNNWW', 'WNNWN','NWNWN');
253 static public function compute($code, $crc, $type){
254 if (! $crc) {
255 if (strlen($code) % 2) $code = '0' . $code;
256 } else {
257 if ( ($type == 'int25') && (strlen($code) % 2 == 0) ) $code = '0' . $code;
258 $odd = true;
259 $sum = 0;
260 for($i=strlen($code)-1; $i>-1; $i--){
261 $v = intval($code[$i]);
262 $sum += $odd ? 3 * $v : $v;
263 $odd = ! $odd;
265 $code .= (string) ((10 - $sum % 10) % 10);
267 return($code);
270 static public function getDigit($code, $crc, $type){
271 $code = self::compute($code, $crc, $type);
272 if ($code == '') return($code);
273 $result = '';
275 if ($type == 'int25') { // Interleaved 2 of 5
276 // start
277 $result .= '1010';
279 // digits + CRC
280 $end = strlen($code) / 2;
281 for($i=0; $i<$end; $i++){
282 $c1 = $code[2*$i];
283 $c2 = $code[2*$i+1];
284 for($j=0; $j<5; $j++){
285 $result .= '1';
286 if (self::$encoding[$c1][$j] == 'W') $result .= '1';
287 $result .= '0';
288 if (self::$encoding[$c2][$j] == 'W') $result .= '0';
291 // stop
292 $result .= '1101';
293 } else if ($type == 'std25') {
294 // Standard 2 of 5 is a numeric-only barcode that has been in use a long time.
295 // 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.
296 // The code is self-checking and does not include a checksum.
298 // start
299 $result .= '11011010';
301 // digits + CRC
302 $end = strlen($code);
303 for($i=0; $i<$end; $i++){
304 $c = $code[$i];
305 for($j=0; $j<5; $j++){
306 $result .= '1';
307 if (self::$encoding[$c][$j] == 'W') $result .= '11';
308 $result .= '0';
311 // stop
312 $result .= '11010110';
314 return($result);
319 class BarcodeEAN {
320 static private $encoding = array(
321 array('0001101', '0100111', '1110010'),
322 array('0011001', '0110011', '1100110'),
323 array('0010011', '0011011', '1101100'),
324 array('0111101', '0100001', '1000010'),
325 array('0100011', '0011101', '1011100'),
326 array('0110001', '0111001', '1001110'),
327 array('0101111', '0000101', '1010000'),
328 array('0111011', '0010001', '1000100'),
329 array('0110111', '0001001', '1001000'),
330 array('0001011', '0010111', '1110100')
333 static private $first = array('000000','001011','001101','001110','010011','011001','011100','010101','010110','011010');
335 static public function getDigit($code, $type){
336 // Check len (12 for ean13, 7 for ean8)
337 $len = $type == 'ean8' ? 7 : 12;
338 $code = substr($code, 0, $len);
339 if (!preg_match('`[0-9]{'.$len.'}`', $code)) return('');
341 // get checksum
342 $code = self::compute($code, $type);
344 // process analyse
345 $result = '101'; // start
347 if ($type == 'ean8'){
348 // process left part
349 for($i=0; $i<4; $i++){
350 $result .= self::$encoding[intval($code[$i])][0];
353 // center guard bars
354 $result .= '01010';
356 // process right part
357 for($i=4; $i<8; $i++){
358 $result .= self::$encoding[intval($code[$i])][2];
361 } else { // ean13
362 // extract first digit and get sequence
363 $seq = self::$first[ intval($code[0]) ];
365 // process left part
366 for($i=1; $i<7; $i++){
367 $result .= self::$encoding[intval($code[$i])][ intval($seq[$i-1]) ];
370 // center guard bars
371 $result .= '01010';
373 // process right part
374 for($i=7; $i<13; $i++){
375 $result .= self::$encoding[intval($code[$i])][ 2 ];
377 } // ean13
379 $result .= '101'; // stop
380 return($result);
383 static public function compute($code, $type){
384 $len = $type == 'ean13' ? 12 : 7;
385 $code = substr($code, 0, $len);
386 if (!preg_match('`[0-9]{'.$len.'}`', $code)) return('');
387 $sum = 0;
388 $odd = true;
389 for($i=$len-1; $i>-1; $i--){
390 $sum += ($odd ? 3 : 1) * intval($code[$i]);
391 $odd = ! $odd;
393 return($code . ( (string) ((10 - $sum % 10) % 10)));
397 class BarcodeUPC {
399 static public function getDigit($code){
400 if (strlen($code) < 12) {
401 $code = '0' . $code;
403 return BarcodeEAN::getDigit($code, 'ean13');
406 static public function compute($code){
407 if (strlen($code) < 12) {
408 $code = '0' . $code;
410 return substr(BarcodeEAN::compute($code, 'ean13'), 1);
414 class BarcodeMSI {
415 static private $encoding = array(
416 '100100100100', '100100100110', '100100110100', '100100110110',
417 '100110100100', '100110100110', '100110110100', '100110110110',
418 '110100100100', '110100100110');
420 static public function compute($code, $crc){
421 if (is_array($crc)){
422 if ($crc['crc1'] == 'mod10'){
423 $code = self::computeMod10($code);
424 } else if ($crc['crc1'] == 'mod11'){
425 $code = self::computeMod11($code);
427 if ($crc['crc2'] == 'mod10'){
428 $code = self::computeMod10($code);
429 } else if ($crc['crc2'] == 'mod11'){
430 $code = self::computeMod11($code);
432 } else if ($crc){
433 $code = self::computeMod10($code);
435 return($code);
438 static private function computeMod10($code){
439 $len = strlen($code);
440 $toPart1 = $len % 2;
441 $n1 = 0;
442 $sum = 0;
443 for($i=0; $i<$len; $i++){
444 if ($toPart1) {
445 $n1 = 10 * $n1 + intval($code[$i]);
446 } else {
447 $sum += intval($code[$i]);
449 $toPart1 = ! $toPart1;
451 $s1 = (string) (2 * $n1);
452 $len = strlen($s1);
453 for($i=0; $i<$len; $i++){
454 $sum += intval($s1[$i]);
456 return($code . ( (string) (10 - $sum % 10) % 10));
459 static private function computeMod11($code){
460 $sum = 0;
461 $weight = 2;
462 for($i=strlen($code)-1; $i>-1; $i--){
463 $sum += $weight * intval($code[$i]);
464 $weight = $weight == 7 ? 2 : $weight + 1;
466 return($code . ( (string) (11 - $sum % 11) % 11) );
469 static public function getDigit($code, $crc){
470 if (preg_match('`[^0-9]`', $code)) return '';
471 $index = 0;
472 $result = '';
474 $code = self::compute($code, false);
476 // start
477 $result = '110';
479 // digits
480 $len = strlen($code);
481 for($i=0; $i<$len; $i++){
482 $result .= self::$encoding[ intval($code[$i]) ];
485 // stop
486 $result .= '1001';
488 return($result);
492 class Barcode11 {
493 static private $encoding = array(
494 '101011', '1101011', '1001011', '1100101',
495 '1011011', '1101101', '1001101', '1010011',
496 '1101001', '110101', '101101');
498 static public function getDigit($code){
499 if (preg_match('`[^0-9\-]`', $code)) return '';
500 $result = '';
501 $intercharacter = '0';
503 // start
504 $result = '1011001' . $intercharacter;
506 // digits
507 $len = strlen($code);
508 for($i=0; $i<$len; $i++){
509 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
510 $result .= self::$encoding[ $index ] . $intercharacter;
513 // checksum
514 $weightC = 0;
515 $weightSumC = 0;
516 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
517 $weightSumK = 0;
518 for($i=$len-1; $i>-1; $i--){
519 $weightC = $weightC == 10 ? 1 : $weightC + 1;
520 $weightK = $weightK == 10 ? 1 : $weightK + 1;
522 $index = $code[$i] == '-' ? 10 : intval($code[$i]);
524 $weightSumC += $weightC * $index;
525 $weightSumK += $weightK * $index;
528 $c = $weightSumC % 11;
529 $weightSumK += $c;
530 $k = $weightSumK % 11;
532 $result .= self::$encoding[$c] . $intercharacter;
534 if ($len >= 10){
535 $result .= self::$encoding[$k] . $intercharacter;
538 // stop
539 $result .= '1011001';
541 return($result);
545 class Barcode39 {
546 static private $encoding = array(
547 '101001101101', '110100101011', '101100101011', '110110010101',
548 '101001101011', '110100110101', '101100110101', '101001011011',
549 '110100101101', '101100101101', '110101001011', '101101001011',
550 '110110100101', '101011001011', '110101100101', '101101100101',
551 '101010011011', '110101001101', '101101001101', '101011001101',
552 '110101010011', '101101010011', '110110101001', '101011010011',
553 '110101101001', '101101101001', '101010110011', '110101011001',
554 '101101011001', '101011011001', '110010101011', '100110101011',
555 '110011010101', '100101101011', '110010110101', '100110110101',
556 '100101011011', '110010101101', '100110101101', '100100100101',
557 '100100101001', '100101001001', '101001001001', '100101101101');
558 static public function getDigit($code){
559 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*';
560 $result = '';
561 $intercharacter = '0';
563 if (strpos($code, '*') !== false) return('');
565 // Add Start and Stop charactere : *
566 $code = strtoupper('*' . $code . '*');
568 $len = strlen($code);
569 for($i=0; $i<$len; $i++){
570 $index = strpos($table, $code[$i]);
571 if ($index === false) return('');
572 if ($i > 0) $result .= $intercharacter;
573 $result .= self::$encoding[ $index ];
575 return($result);
579 class Barcode93{
580 static private $encoding = array(
581 '100010100', '101001000', '101000100', '101000010',
582 '100101000', '100100100', '100100010', '101010000',
583 '100010010', '100001010', '110101000', '110100100',
584 '110100010', '110010100', '110010010', '110001010',
585 '101101000', '101100100', '101100010', '100110100',
586 '100011010', '101011000', '101001100', '101000110',
587 '100101100', '100010110', '110110100', '110110010',
588 '110101100', '110100110', '110010110', '110011010',
589 '101101100', '101100110', '100110110', '100111010',
590 '100101110', '111010100', '111010010', '111001010',
591 '101101110', '101110110', '110101110', '100100110',
592 '111011010', '111010110', '100110010', '101011110');
594 static public function getDigit($code, $crc){
595 $table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%____*'; // _ => ($), (%), (/) et (+)
596 $result = '';
598 if (strpos($code, '*') !== false) return('');
600 $code = strtoupper($code);
602 // start : *
603 $result .= self::$encoding[47];
605 // digits
606 $len = strlen($code);
607 for($i=0; $i<$len; $i++){
608 $c = $code[$i];
609 $index = strpos($table, $c);
610 if ( ($c == '_') || ($index === false) ) return('');
611 $result .= self::$encoding[ $index ];
614 // checksum
615 if ($crc){
616 $weightC = 0;
617 $weightSumC = 0;
618 $weightK = 1; // start at 1 because the right-most character is 'C' checksum
619 $weightSumK = 0;
620 for($i=$len-1; $i>-1; $i--){
621 $weightC = $weightC == 20 ? 1 : $weightC + 1;
622 $weightK = $weightK == 15 ? 1 : $weightK + 1;
624 $index = strpos($table, $code[$i]);
626 $weightSumC += $weightC * $index;
627 $weightSumK += $weightK * $index;
630 $c = $weightSumC % 47;
631 $weightSumK += $c;
632 $k = $weightSumK % 47;
634 $result .= self::$encoding[$c];
635 $result .= self::$encoding[$k];
638 // stop : *
639 $result .= self::$encoding[47];
641 // Terminaison bar
642 $result .= '1';
643 return($result);
647 class Barcode128 {
648 static private $encoding = array(
649 '11011001100', '11001101100', '11001100110', '10010011000',
650 '10010001100', '10001001100', '10011001000', '10011000100',
651 '10001100100', '11001001000', '11001000100', '11000100100',
652 '10110011100', '10011011100', '10011001110', '10111001100',
653 '10011101100', '10011100110', '11001110010', '11001011100',
654 '11001001110', '11011100100', '11001110100', '11101101110',
655 '11101001100', '11100101100', '11100100110', '11101100100',
656 '11100110100', '11100110010', '11011011000', '11011000110',
657 '11000110110', '10100011000', '10001011000', '10001000110',
658 '10110001000', '10001101000', '10001100010', '11010001000',
659 '11000101000', '11000100010', '10110111000', '10110001110',
660 '10001101110', '10111011000', '10111000110', '10001110110',
661 '11101110110', '11010001110', '11000101110', '11011101000',
662 '11011100010', '11011101110', '11101011000', '11101000110',
663 '11100010110', '11101101000', '11101100010', '11100011010',
664 '11101111010', '11001000010', '11110001010', '10100110000',
665 '10100001100', '10010110000', '10010000110', '10000101100',
666 '10000100110', '10110010000', '10110000100', '10011010000',
667 '10011000010', '10000110100', '10000110010', '11000010010',
668 '11001010000', '11110111010', '11000010100', '10001111010',
669 '10100111100', '10010111100', '10010011110', '10111100100',
670 '10011110100', '10011110010', '11110100100', '11110010100',
671 '11110010010', '11011011110', '11011110110', '11110110110',
672 '10101111000', '10100011110', '10001011110', '10111101000',
673 '10111100010', '11110101000', '11110100010', '10111011110',
674 '10111101110', '11101011110', '11110101110', '11010000100',
675 '11010010000', '11010011100', '11000111010');
676 static public function getDigit($code){
677 $tableB = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
678 $result = "";
679 $sum = 0;
680 $isum = 0;
681 $i = 0;
682 $j = 0;
683 $value = 0;
685 // check each characters
686 $len = strlen($code);
687 for($i=0; $i<$len; $i++){
688 if (strpos($tableB, $code[$i]) === false) return("");
691 // check firsts characters : start with C table only if enought numeric
692 $tableCActivated = $len> 1;
693 $c = '';
694 for($i=0; $i<3 && $i<$len; $i++){
695 $tableCActivated &= preg_match('`[0-9]`', $code[$i]);
698 $sum = $tableCActivated ? 105 : 104;
700 // start : [105] : C table or [104] : B table
701 $result = self::$encoding[ $sum ];
703 $i = 0;
704 while( $i < $len ){
705 if (! $tableCActivated){
706 $j = 0;
707 // check next character to activate C table if interresting
708 while ( ($i + $j < $len) && preg_match('`[0-9]`', $code[$i+$j]) ) $j++;
710 // 6 min everywhere or 4 mini at the end
711 $tableCActivated = ($j > 5) || (($i + $j - 1 == $len) && ($j > 3));
713 if ( $tableCActivated ){
714 $result .= self::$encoding[ 99 ]; // C table
715 $sum += ++$isum * 99;
717 // 2 min for table C so need table B
718 } 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
719 $tableCActivated = false;
720 $result .= self::$encoding[ 100 ]; // B table
721 $sum += ++$isum * 100;
724 if ( $tableCActivated ) {
725 $value = intval(substr($code, $i, 2)); // Add two characters (numeric)
726 $i += 2;
727 } else {
728 $value = strpos($tableB, $code[$i]); // Add one character
729 $i++;
731 $result .= self::$encoding[ $value ];
732 $sum += ++$isum * $value;
735 // Add CRC
736 $result .= self::$encoding[ $sum % 103 ];
738 // Stop
739 $result .= self::$encoding[ 106 ];
741 // Termination bar
742 $result .= '11';
744 return($result);
748 class BarcodeCodabar {
749 static private $encoding = array(
750 '101010011', '101011001', '101001011', '110010101',
751 '101101001', '110101001', '100101011', '100101101',
752 '100110101', '110100101', '101001101', '101100101',
753 '1101011011', '1101101011', '1101101101', '1011011011',
754 '1011001001', '1010010011', '1001001011', '1010011001');
756 static public function getDigit($code){
757 $table = '0123456789-$:/.+';
758 $result = '';
759 $intercharacter = '0';
761 // add start : A->D : arbitrary choose A
762 $result .= self::$encoding[16] . $intercharacter;
764 $len = strlen($code);
765 for($i=0; $i<$len; $i++){
766 $index = strpos($table, $code[$i]);
767 if ($index === false) return('');
768 $result .= self::$encoding[ $index ] . $intercharacter;
771 // add stop : A->D : arbitrary choose A
772 $result .= self::$encoding[16];
773 return($result);
777 class BarcodeDatamatrix {
778 static private $lengthRows = array(
779 10, 12, 14, 16, 18, 20, 22, 24, 26, // 24 squares et 6 rectangular
780 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
781 8, 8, 12, 12, 16, 16);
782 static private $lengthCols = array(
783 10, 12, 14, 16, 18, 20, 22, 24, 26, // Number of columns for the entire datamatrix
784 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144,
785 18, 32, 26, 36, 36, 48);
786 static private $dataCWCount = array(
787 3, 5, 8, 12, 18, 22, 30, 36, // Number of data codewords for the datamatrix
788 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816, 1050,
789 1304, 1558, 5, 10, 16, 22, 32, 49);
790 static private $solomonCWCount = array(
791 5, 7, 10, 12, 14, 18, 20, 24, 28, // Number of Reed-Solomon codewords for the datamatrix
792 36, 42, 48, 56, 68, 84, 112, 144, 192, 224, 272, 336, 408, 496, 620,
793 7, 11, 14, 18, 24, 28);
794 static private $dataRegionRows = array(
795 8, 10, 12, 14, 16, 18, 20, 22, // Number of rows per region
796 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
797 6, 6, 10, 10, 14, 14);
798 static private $dataRegionCols = array(
799 8, 10, 12, 14, 16, 18, 20, 22, // Number of columns per region
800 24, 14, 16, 18, 20, 22, 24, 14, 16, 18, 20, 22, 24, 18, 20, 22,
801 16, 14, 24, 16, 16, 22);
802 static private $regionRows = array(
803 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per row
804 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
805 1, 1, 1, 1, 1, 1);
806 static private $regionCols = array(
807 1, 1, 1, 1, 1, 1, 1, 1, // Number of regions per column
808 1, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 6, 6, 6,
809 1, 2, 1, 2, 2, 2);
810 static private $interleavedBlocks = array(
811 1, 1, 1, 1, 1, 1, 1, 1, // Number of blocks
812 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 6, 6, 8, 8,
813 1, 1, 1, 1, 1, 1);
814 static private $logTab = array(
815 -255, 255, 1, 240, 2, 225, 241, 53, 3, // Table of log for the Galois field
816 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106, 134, 28,
817 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115,
818 103, 228, 78, 107, 125, 135, 8, 29, 162, 244, 186, 141, 180, 45, 99,
819 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76, 220, 217, 197,
820 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171,
821 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187,
822 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, 57, 147,
823 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7,
824 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
825 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194,
826 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127,
827 247, 146, 66, 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73,
828 164, 144, 85, 170, 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82,
829 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112,
830 232, 21, 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149,
831 129, 19, 155, 59, 249, 70, 214, 250, 168, 71, 201, 156, 64, 60, 237,
832 130, 111, 20, 93, 122, 177, 150);
833 static private $aLogTab = array(
834 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, // Table of aLog for the Galois field
835 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219, 155, 27, 54,
836 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36,
837 72, 144, 13, 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56,
838 112, 224, 237, 247, 195, 171, 123, 246, 193, 175, 115, 230, 225, 239,
839 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190,
840 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106,
841 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, 217, 159, 19, 38, 76,
842 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223,
843 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113,
844 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, 214, 129,
845 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, 127,
846 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
847 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161,
848 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132,
849 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248,
850 221, 151, 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75,
851 150, 1);
852 static private function champGaloisMult($a, $b){ // MULTIPLICATION IN GALOIS FIELD GF(2^8)
853 if(!$a || !$b) return 0;
854 return self::$aLogTab[(self::$logTab[$a] + self::$logTab[$b]) % 255];
856 static private function champGaloisDoub($a, $b){ // THE OPERATION a * 2^b IN GALOIS FIELD GF(2^8)
857 if (!$a) return 0;
858 if (!$b) return $a;
859 return self::$aLogTab[(self::$logTab[$a] + $b) % 255];
861 static private function champGaloisSum($a, $b){ // SUM IN GALOIS FIELD GF(2^8)
862 return $a ^ $b;
864 static private function selectIndex($dataCodeWordsCount, $rectangular){ // CHOOSE THE GOOD INDEX FOR TABLES
865 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>1558) && !$rectangular) return -1;
866 if (($dataCodeWordsCount<1 || $dataCodeWordsCount>49) && $rectangular) return -1;
868 $n = $rectangular ? 24 : 0;
870 while (self::$dataCWCount[$n] < $dataCodeWordsCount) $n++;
871 return $n;
873 static private function encodeDataCodeWordsASCII($text) {
874 $dataCodeWords = array();
875 $n = 0;
876 $len = strlen($text);
877 for ($i=0; $i<$len; $i++){
878 $c = ord($text[$i]);
879 if ($c > 127) {
880 $dataCodeWords[$n] = 235;
881 $c -= 127;
882 $n++;
883 } else if (($c>=48 && $c<=57) && ($i+1<$len) && (preg_match('`[0-9]`', $text[$i+1]))) {
884 $c = (($c - 48) * 10) + intval($text[$i+1]);
885 $c += 130;
886 $i++;
887 } else $c++;
888 $dataCodeWords[$n] = $c;
889 $n++;
891 return $dataCodeWords;
893 static private function addPadCW(&$tab, $from, $to){
894 if ($from >= $to) return ;
895 $tab[$from] = 129;
896 for ($i=$from+1; $i<$to; $i++){
897 $r = ((149 * ($i+1)) % 253) + 1;
898 $tab[$i] = (129 + $r) % 254;
901 static private function calculSolFactorTable($solomonCWCount){ // CALCULATE THE REED SOLOMON FACTORS
902 $g = array_fill(0, $solomonCWCount+1, 1);
903 for($i = 1; $i <= $solomonCWCount; $i++) {
904 for($j = $i - 1; $j >= 0; $j--) {
905 $g[$j] = self::champGaloisDoub($g[$j], $i);
906 if($j > 0) $g[$j] = self::champGaloisSum($g[$j], $g[$j-1]);
909 return $g;
911 static private function addReedSolomonCW($nSolomonCW, $coeffTab, $nDataCW, &$dataTab, $blocks){ // Add the Reed Solomon codewords
912 $errorBlocks = $nSolomonCW / $blocks;
913 $correctionCW = array();
915 for($k = 0; $k < $blocks; $k++) {
916 for ($i=0; $i < $errorBlocks; $i++) $correctionCW[$i] = 0;
918 for ($i=$k; $i<$nDataCW; $i+=$blocks){
919 $temp = self::champGaloisSum($dataTab[$i], $correctionCW[$errorBlocks-1]);
920 for ($j=$errorBlocks-1; $j>=0; $j--){
921 if ( !$temp ) {
922 $correctionCW[$j] = 0;
923 } else {
924 $correctionCW[$j] = self::champGaloisMult($temp, $coeffTab[$j]);
926 if ($j>0) $correctionCW[$j] = self::champGaloisSum($correctionCW[$j-1], $correctionCW[$j]);
929 // Renversement des blocs calcules
930 $j = $nDataCW + $k;
931 for ($i=$errorBlocks-1; $i>=0; $i--){
932 $dataTab[$j] = $correctionCW[$i];
933 $j=$j+$blocks;
936 return $dataTab;
938 static private function getBits($entier){ // Transform integer to tab of bits
939 $bits = array();
940 for ($i=0; $i<8; $i++){
941 $bits[$i] = $entier & (128 >> $i) ? 1 : 0;
943 return $bits;
945 static private function next($etape, $totalRows, $totalCols, $codeWordsBits, &$datamatrix, &$assigned){ // Place codewords into the matrix
946 $chr = 0; // Place of the 8st bit from the first character to [4][0]
947 $row = 4;
948 $col = 0;
950 do {
951 // Check for a special case of corner
952 if(($row == $totalRows) && ($col == 0)){
953 self::patternShapeSpecial1($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
954 $chr++;
955 } else if(($etape<3) && ($row == $totalRows-2) && ($col == 0) && ($totalCols%4 != 0)){
956 self::patternShapeSpecial2($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
957 $chr++;
958 } else if(($row == $totalRows-2) && ($col == 0) && ($totalCols%8 == 4)){
959 self::patternShapeSpecial3($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
960 $chr++;
962 else if(($row == $totalRows+4) && ($col == 2) && ($totalCols%8 == 0)){
963 self::patternShapeSpecial4($datamatrix, $assigned, $codeWordsBits[$chr], $totalRows, $totalCols);
964 $chr++;
967 // Go up and right in the datamatrix
968 do {
969 if(($row < $totalRows) && ($col >= 0) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)) {
970 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
971 $chr++;
973 $row -= 2;
974 $col += 2;
975 } while (($row >= 0) && ($col < $totalCols));
976 $row += 1;
977 $col += 3;
979 // Go down and left in the datamatrix
980 do {
981 if(($row >= 0) && ($col < $totalCols) && (!isset($assigned[$row][$col]) || $assigned[$row][$col]!=1)){
982 self::patternShapeStandard($datamatrix, $assigned, $codeWordsBits[$chr], $row, $col, $totalRows, $totalCols);
983 $chr++;
985 $row += 2;
986 $col -= 2;
987 } while (($row < $totalRows) && ($col >=0));
988 $row += 3;
989 $col += 1;
990 } while (($row < $totalRows) || ($col < $totalCols));
992 static private function patternShapeStandard(&$datamatrix, &$assigned, $bits, $row, $col, $totalRows, $totalCols){ // Place bits in the matrix (standard or special case)
993 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $row-2, $col-2, $totalRows, $totalCols);
994 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $row-2, $col-1, $totalRows, $totalCols);
995 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $row-1, $col-2, $totalRows, $totalCols);
996 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], $row-1, $col-1, $totalRows, $totalCols);
997 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], $row-1, $col, $totalRows, $totalCols);
998 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], $row, $col-2, $totalRows, $totalCols);
999 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], $row, $col-1, $totalRows, $totalCols);
1000 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], $row, $col, $totalRows, $totalCols);
1002 static private function patternShapeSpecial1(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols ){
1003 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1004 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, 1, $totalRows, $totalCols);
1005 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 2, $totalRows, $totalCols);
1006 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1007 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1008 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1009 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1010 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1012 static private function patternShapeSpecial2(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols ){
1013 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1014 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1015 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1016 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-4, $totalRows, $totalCols);
1017 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-3, $totalRows, $totalCols);
1018 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 0, $totalCols-2, $totalRows, $totalCols);
1019 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 0, $totalCols-1, $totalRows, $totalCols);
1020 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1022 static private function patternShapeSpecial3(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols ){
1023 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-3, 0, $totalRows, $totalCols);
1024 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-2, 0, $totalRows, $totalCols);
1025 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], $totalRows-1, 0, $totalRows, $totalCols);
1026 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1027 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1028 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-1, $totalRows, $totalCols);
1029 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 2, $totalCols-1, $totalRows, $totalCols);
1030 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 3, $totalCols-1, $totalRows, $totalCols);
1032 static private function patternShapeSpecial4(&$datamatrix, &$assigned, $bits, $totalRows, $totalCols ){
1033 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[0], $totalRows-1, 0, $totalRows, $totalCols);
1034 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[1], $totalRows-1, $totalCols-1, $totalRows, $totalCols);
1035 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[2], 0, $totalCols-3, $totalRows, $totalCols);
1036 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[3], 0, $totalCols-2, $totalRows, $totalCols);
1037 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[4], 0, $totalCols-1, $totalRows, $totalCols);
1038 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[5], 1, $totalCols-3, $totalRows, $totalCols);
1039 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[6], 1, $totalCols-2, $totalRows, $totalCols);
1040 self::placeBitInDatamatrix($datamatrix, $assigned, $bits[7], 1, $totalCols-1, $totalRows, $totalCols);
1042 static private function placeBitInDatamatrix(&$datamatrix, &$assigned, $bit, $row, $col, $totalRows, $totalCols){ // Put a bit into the matrix
1043 if ($row < 0) {
1044 $row += $totalRows;
1045 $col += 4 - (($totalRows+4)%8);
1047 if ($col < 0) {
1048 $col += $totalCols;
1049 $row += 4 - (($totalCols+4)%8);
1051 if (!isset($assigned[$row][$col]) || $assigned[$row][$col] != 1) {
1052 $datamatrix[$row][$col] = $bit;
1053 $assigned[$row][$col] = 1;
1056 static private function addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW){ // Add the finder pattern
1057 $totalRowsCW = ($rowsRegionCW+2) * $rowsRegion;
1058 $totalColsCW = ($colsRegionCW+2) * $colsRegion;
1060 $datamatrixTemp = array();
1061 $datamatrixTemp[0] = array_fill(0, $totalColsCW+2, 0);
1063 for ($i=0; $i<$totalRowsCW; $i++){
1064 $datamatrixTemp[$i+1] = array();
1065 $datamatrixTemp[$i+1][0] = 0;
1066 $datamatrixTemp[$i+1][$totalColsCW+1] = 0;
1067 for ($j=0; $j<$totalColsCW; $j++){
1068 if ($i%($rowsRegionCW+2) == 0){
1069 if ($j%2 == 0){
1070 $datamatrixTemp[$i+1][$j+1] = 1;
1071 } else {
1072 $datamatrixTemp[$i+1][$j+1] = 0;
1074 } else if ($i%($rowsRegionCW+2) == $rowsRegionCW+1){
1075 $datamatrixTemp[$i+1][$j+1] = 1;
1076 } else if ($j%($colsRegionCW+2) == $colsRegionCW+1){
1077 if ($i%2 == 0){
1078 $datamatrixTemp[$i+1][$j+1] = 0;
1079 } else {
1080 $datamatrixTemp[$i+1][$j+1] = 1;
1082 } else if ($j%($colsRegionCW+2) == 0){
1083 $datamatrixTemp[$i+1][$j+1] = 1;
1084 } else{
1085 $datamatrixTemp[$i+1][$j+1] = 0;
1086 $datamatrixTemp[$i+1][$j+1] = $datamatrix[$i-1-(2*(floor($i/($rowsRegionCW+2))))][$j-1-(2*(floor($j/($colsRegionCW+2))))]; // todo : parseInt => ?
1090 $datamatrixTemp[$totalRowsCW+1] = array();
1091 for ($j=0; $j<$totalColsCW+2; $j++){
1092 $datamatrixTemp[$totalRowsCW+1][$j] = 0;
1094 return $datamatrixTemp;
1096 static public function getDigit($text, $rectangular){
1097 $dataCodeWords = self::encodeDataCodeWordsASCII($text); // Code the text in the ASCII mode
1098 $dataCWCount = count($dataCodeWords);
1099 $index = self::selectIndex($dataCWCount, $rectangular); // Select the index for the data tables
1100 $totalDataCWCount = self::$dataCWCount[$index]; // Number of data CW
1101 $solomonCWCount = self::$solomonCWCount[$index]; // Number of Reed Solomon CW
1102 $totalCWCount = $totalDataCWCount + $solomonCWCount; // Number of CW
1103 $rowsTotal = self::$lengthRows[$index]; // Size of symbol
1104 $colsTotal = self::$lengthCols[$index];
1105 $rowsRegion = self::$regionRows[$index]; // Number of region
1106 $colsRegion = self::$regionCols[$index];
1107 $rowsRegionCW = self::$dataRegionRows[$index];
1108 $colsRegionCW = self::$dataRegionCols[$index];
1109 $rowsLengthMatrice = $rowsTotal-2*$rowsRegion; // Size of matrice data
1110 $colsLengthMatrice = $colsTotal-2*$colsRegion;
1111 $blocks = self::$interleavedBlocks[$index]; // Number of Reed Solomon blocks
1112 $errorBlocks = $solomonCWCount / $blocks;
1114 self::addPadCW($dataCodeWords, $dataCWCount, $totalDataCWCount); // Add codewords pads
1116 $g = self::calculSolFactorTable($errorBlocks); // Calculate correction coefficients
1118 self::addReedSolomonCW($solomonCWCount, $g, $totalDataCWCount, $dataCodeWords, $blocks); // Add Reed Solomon codewords
1120 $codeWordsBits = array(); // Calculte bits from codewords
1121 for ($i=0; $i<$totalCWCount; $i++){
1122 $codeWordsBits[$i] = self::getBits($dataCodeWords[$i]);
1125 $datamatrix = array_fill(0, $colsLengthMatrice, array());
1126 $assigned = array_fill(0, $colsLengthMatrice, array());
1128 // Add the bottom-right corner if needed
1129 if ( (($rowsLengthMatrice * $colsLengthMatrice) % 8) == 4) {
1130 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1131 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1132 $datamatrix[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 0;
1133 $datamatrix[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 0;
1134 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-2] = 1;
1135 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-1] = 1;
1136 $assigned[$rowsLengthMatrice-1][$colsLengthMatrice-2] = 1;
1137 $assigned[$rowsLengthMatrice-2][$colsLengthMatrice-1] = 1;
1140 // Put the codewords into the matrix
1141 self::next(0,$rowsLengthMatrice,$colsLengthMatrice, $codeWordsBits, $datamatrix, $assigned);
1143 // Add the finder pattern
1144 $datamatrix = self::addFinderPattern($datamatrix, $rowsRegion, $colsRegion, $rowsRegionCW, $colsRegionCW);
1146 return $datamatrix;