ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PDF417 Class Reference

Class to create PDF417 barcode arrays for TCPDF class. More...

+ Collaboration diagram for PDF417:

Public Member Functions

 __construct ($code, $ecl=-1, $aspectratio=2, $macro=array())
 This is the class constructor. More...
 
 getBarcodeArray ()
 Returns a barcode array which is readable by TCPDF. More...
 

Protected Member Functions

 getErrorCorrectionLevel ($ecl, $numcw)
 Returns the error correction level (0-8) to be used. More...
 
 getErrorCorrection ($cw, $ecl)
 Returns the error correction codewords. More...
 
 getInputSequences ($code)
 Create array of sequences from input. More...
 
 getCompaction ($mode, $code, $addmode=true)
 Compact data by mode. More...
 

Protected Attributes

 $barcode_array = array()
 Barcode array to be returned which is readable by TCPDF. More...
 
 $start_pattern = '11111111010101000'
 Start pattern. More...
 
 $stop_pattern = '111111101000101001'
 Stop pattern. More...
 
 $textsubmodes
 Array of text Compaction Sub-Modes (values 0xFB - 0xFF are used for submode changers). More...
 
 $textlatch
 Array of switching codes for Text Compaction Sub-Modes. More...
 
 $clusters
 Clusters of codewords (0, 3, 6)
Values are hex equivalents of binary representation of bars (1 = bar, 0 = space). More...
 
 $rsfactors
 Array of factors of the Reed-Solomon polynomial equations used for error correction; one sub array for each correction level (0-8). More...
 

Detailed Description

Class to create PDF417 barcode arrays for TCPDF class.

PDF417 (ISO/IEC 15438:2006) is a 2-dimensional stacked bar code created by Symbol Technologies in 1991.

Definition at line 93 of file pdf417.php.

Constructor & Destructor Documentation

◆ __construct()

PDF417::__construct (   $code,
  $ecl = -1,
  $aspectratio = 2,
  $macro = array() 
)

This is the class constructor.

Creates a PDF417 object

Parameters
$code(string) code to represent using PDF417
$ecl(int) error correction level (0-8); default -1 = automatic correction level
$aspectratio(float) the width to height of the symbol (excluding quiet zones)
$macro(array) information for macro block

Definition at line 532 of file pdf417.php.

References $barcode_array, $c, $code, $cols, $h, $i, $r, $row, $rows, $size, getCompaction(), getErrorCorrection(), getErrorCorrectionLevel(), and getInputSequences().

532  {
533  $barcode_array = array();
534  if ((is_null($code)) OR ($code == '\0') OR ($code == '')) {
535  return false;
536  }
537  // get the input sequence array
538  $sequence = $this->getInputSequences($code);
539  $codewords = array(); // array of code-words
540  foreach($sequence as $seq) {
541  $cw = $this->getCompaction($seq[0], $seq[1], true);
542  $codewords = array_merge($codewords, $cw);
543  }
544  if ($codewords[0] == 900) {
545  // Text Alpha is the default mode, so remove the first code
546  array_shift($codewords);
547  }
548  // count number of codewords
549  $numcw = count($codewords);
550  if ($numcw > 925) {
551  // reached maximum data codeword capacity
552  return false;
553  }
554  // build macro control block codewords
555  if (!empty($macro)) {
556  $macrocw = array();
557  // beginning of macro control block
558  $macrocw[] = 928;
559  // segment index
560  $cw = $this->getCompaction(902, sprintf('%05d', $macro['segment_index']), false);
561  $macrocw = array_merge($macrocw, $cw);
562  // file ID
563  $cw = $this->getCompaction(900, $macro['file_id'], false);
564  $macrocw = array_merge($macrocw, $cw);
565  // optional fields
566  $optmodes = array(900,902,902,900,900,902,902);
567  $optsize = array(-1,2,4,-1,-1,-1,2);
568  foreach ($optmodes as $k => $omode) {
569  if (isset($macro['option_'.$k])) {
570  $macrocw[] = 923;
571  $macrocw[] = $k;
572  if ($optsize[$k] == 2) {
573  $macro['option_'.$k] = sprintf('%05d', $macro['option_'.$k]);
574  } elseif ($optsize[$k] == 4) {
575  $macro['option_'.$k] = sprintf('%010d', $macro['option_'.$k]);
576  }
577  $cw = $this->getCompaction($omode, $macro['option_'.$k], false);
578  $macrocw = array_merge($macrocw, $cw);
579  }
580  }
581  if ($macro['segment_index'] == ($macro['segment_total'] - 1)) {
582  // end of control block
583  $macrocw[] = 922;
584  }
585  // update total codewords
586  $numcw += count($macrocw);
587  }
588  // set error correction level
589  $ecl = $this->getErrorCorrectionLevel($ecl, $numcw);
590  // number of codewords for error correction
591  $errsize = (2 << $ecl);
592  // calculate number of columns (number of codewords per row) and rows
593  $nce = ($numcw + $errsize + 1);
594  $cols = round((sqrt(4761 + (68 * $aspectratio * ROWHEIGHT * $nce)) - 69) / 34);
595  // adjust cols
596  if ($cols < 1) {
597  $cols = 1;
598  } elseif ($cols > 30) {
599  $cols = 30;
600  }
601  $rows = ceil($nce / $cols);
602  $size = ($cols * $rows);
603  // adjust rows
604  if (($rows < 3) OR ($rows > 90)) {
605  if ($rows < 3) {
606  $rows = 3;
607  } elseif ($rows > 90) {
608  $rows = 90;
609  }
610  $cols = ceil($size / $rows);
611  $size = ($cols * $rows);
612  }
613  if ($size > 928) {
614  // set dimensions to get maximum capacity
615  if (abs($aspectratio - (17 * 29 / 32)) < abs($aspectratio - (17 * 16 / 58))) {
616  $cols = 29;
617  $rows = 32;
618  } else {
619  $cols = 16;
620  $rows = 58;
621  }
622  $size = 928;
623  }
624  // calculate padding
625  $pad = ($size - $nce);
626  if ($pad > 0) {
627  if (($size - $rows) == $nce) {
628  --$rows;
629  $size -= $rows;
630  } else {
631  // add pading
632  $codewords = array_merge($codewords, array_fill(0, $pad, 900));
633  }
634  }
635  if (!empty($macro)) {
636  // add macro section
637  $codewords = array_merge($codewords, $macrocw);
638  }
639  // Symbol Length Descriptor (number of data codewords including Symbol Length Descriptor and pad codewords)
640  $sld = $size - $errsize;
641  // add symbol length description
642  array_unshift($codewords, $sld);
643  // calculate error correction
644  $ecw = $this->getErrorCorrection($codewords, $ecl);
645  // add error correction codewords
646  $codewords = array_merge($codewords, $ecw);
647  // add horizontal quiet zones to start and stop patterns
648  $pstart = str_repeat('0', QUIETH).$this->start_pattern;
649  $pstop = $this->stop_pattern.str_repeat('0', QUIETH);
650  $barcode_array['num_rows'] = ($rows * ROWHEIGHT) + (2 * QUIETV);
651  $barcode_array['num_cols'] = (($cols + 2) * 17) + 35 + (2 * QUIETH);
652  $barcode_array['bcode'] = array();
653  // build rows for vertical quiet zone
654  if (QUIETV > 0) {
655  $empty_row = array_fill(0, $barcode_array['num_cols'], 0);
656  for ($i = 0; $i < QUIETV; ++$i) {
657  // add vertical quiet rows
658  $barcode_array['bcode'][] = $empty_row;
659  }
660  }
661  $k = 0; // codeword index
662  $cid = 0; // initial cluster
663  // for each row
664  for ($r = 0; $r < $rows; ++$r) {
665  // row start code
666  $row = $pstart;
667  switch ($cid) {
668  case 0: {
669  $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3));
670  break;
671  }
672  case 1: {
673  $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3));
674  break;
675  }
676  case 2: {
677  $L = ((30 * intval($r / 3)) + ($cols - 1));
678  break;
679  }
680  }
681  // left row indicator
682  $row .= sprintf('%17b', $this->clusters[$cid][$L]);
683  // for each column
684  for ($c = 0; $c < $cols; ++$c) {
685  $row .= sprintf('%17b', $this->clusters[$cid][$codewords[$k]]);
686  ++$k;
687  }
688  switch ($cid) {
689  case 0: {
690  $L = ((30 * intval($r / 3)) + ($cols - 1));
691  break;
692  }
693  case 1: {
694  $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3));
695  break;
696  }
697  case 2: {
698  $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3));
699  break;
700  }
701  }
702  // right row indicator
703  $row .= sprintf('%17b', $this->clusters[$cid][$L]);
704  // row stop code
705  $row .= $pstop;
706  // convert the string to array
707  $arow = preg_split('//', $row, -1, PREG_SPLIT_NO_EMPTY);
708  // duplicate row to get the desired height
709  for ($h = 0; $h < ROWHEIGHT; ++$h) {
710  $barcode_array['bcode'][] = $arow;
711  }
712  ++$cid;
713  if ($cid > 2) {
714  $cid = 0;
715  }
716  }
717  if (QUIETV > 0) {
718  for ($i = 0; $i < QUIETV; ++$i) {
719  // add vertical quiet rows
720  $barcode_array['bcode'][] = $empty_row;
721  }
722  }
723  $this->barcode_array = $barcode_array;
724  }
getCompaction($mode, $code, $addmode=true)
Compact data by mode.
Definition: pdf417.php:873
$size
Definition: RandomTest.php:84
$barcode_array
Barcode array to be returned which is readable by TCPDF.
Definition: pdf417.php:99
$h
$code
Definition: example_050.php:99
getErrorCorrectionLevel($ecl, $numcw)
Returns the error correction level (0-8) to be used.
Definition: pdf417.php:742
getErrorCorrection($cw, $ecl)
Returns the error correction codewords.
Definition: pdf417.php:780
getInputSequences($code)
Create array of sequences from input.
Definition: pdf417.php:816
$r
Definition: example_031.php:79
$row
$rows
Definition: xhr_table.php:10
$i
Definition: disco.tpl.php:19
$cols
Definition: xhr_table.php:11
+ Here is the call graph for this function:

Member Function Documentation

◆ getBarcodeArray()

PDF417::getBarcodeArray ( )

Returns a barcode array which is readable by TCPDF.

Returns
array barcode array readable by TCPDF;

Definition at line 731 of file pdf417.php.

References $barcode_array.

731  {
732  return $this->barcode_array;
733  }
$barcode_array
Barcode array to be returned which is readable by TCPDF.
Definition: pdf417.php:99

◆ getCompaction()

PDF417::getCompaction (   $mode,
  $code,
  $addmode = true 
)
protected

Compact data by mode.

Parameters
$mode(int) compaction mode number
$code(string) data to compact
$addmode(boolean) if true add the mode codeword at first position
Returns
array of codewords

Definition at line 873 of file pdf417.php.

References $code, $d, $i, $rest, $s, and $t.

Referenced by __construct().

873  {
874  $cw = array(); // array of codewords to return
875  switch($mode) {
876  case 900: { // Text Compaction mode latch
877  $submode = 0; // default Alpha sub-mode
878  $txtarr = array(); // array of characters and sub-mode switching characters
879  $codelen = strlen($code);
880  for ($i = 0; $i < $codelen; ++$i) {
881  $chval = ord($code{$i});
882  if (($k = array_search($chval, $this->textsubmodes[$submode])) !== false) {
883  // we are on the same sub-mode
884  $txtarr[] = $k;
885  } else {
886  // the sub-mode is changed
887  for ($s = 0; $s < 4; ++$s) {
888  // search new sub-mode
889  if (($s != $submode) AND (($k = array_search($chval, $this->textsubmodes[$s])) !== false)) {
890  // $s is the new submode
891  if (((($i + 1) == $codelen) OR ((($i + 1) < $codelen) AND (array_search(ord($code{($i + 1)}), $this->textsubmodes[$submode]) !== false))) AND (($s == 3) OR (($s == 0) AND ($submode == 1)))) {
892  // shift (temporary change only for this char)
893  if ($s == 3) {
894  // shift to puntuaction
895  $txtarr[] = 29;
896  } else {
897  // shift from lower to alpha
898  $txtarr[] = 27;
899  }
900  } else {
901  // latch
902  $txtarr = array_merge($txtarr, $this->textlatch[''.$submode.$s]);
903  // set new submode
904  $submode = $s;
905  }
906  // add characted code to array
907  $txtarr[] = $k;
908  break;
909  }
910  }
911  }
912  }
913  $txtarrlen = count($txtarr);
914  if (($txtarrlen % 2) != 0) {
915  // add padding
916  $txtarr[] = 29;
917  ++$txtarrlen;
918  }
919  // calculate codewords
920  for ($i = 0; $i < $txtarrlen; $i += 2) {
921  $cw[] = (30 * $txtarr[$i]) + $txtarr[($i + 1)];
922  }
923  break;
924  }
925  case 901:
926  case 924: { // Byte Compaction mode latch
927  while (($codelen = strlen($code)) > 0) {
928  if ($codelen > 6) {
929  $rest = substr($code, 6);
930  $code = substr($code, 0, 6);
931  $sublen = 6;
932  } else {
933  $rest = '';
934  $sublen = strlen($code);
935  }
936  if ($sublen == 6) {
937  $t = bcmul(''.ord($code[0]), '1099511627776');
938  $t = bcadd($t, bcmul(''.ord($code[1]), '4294967296'));
939  $t = bcadd($t, bcmul(''.ord($code[2]), '16777216'));
940  $t = bcadd($t, bcmul(''.ord($code[3]), '65536'));
941  $t = bcadd($t, bcmul(''.ord($code[4]), '256'));
942  $t = bcadd($t, ''.ord($code[5]));
943  // tmp array for the 6 bytes block
944  $cw6 = array();
945  do {
946  $d = bcmod($t, '900');
947  $t = bcdiv($t, '900');
948  // prepend the value to the beginning of the array
949  array_unshift($cw6, $d);
950  } while ($t != '0');
951  // append the result array at the end
952  $cw = array_merge($cw, $cw6);
953  } else {
954  for ($i = 0; $i < $sublen; ++$i) {
955  $cw[] = ord($code{$i});
956  }
957  }
958  $code = $rest;
959  }
960  break;
961  }
962  case 902: { // Numeric Compaction mode latch
963  while (($codelen = strlen($code)) > 0) {
964  if ($codelen > 44) {
965  $rest = substr($code, 44);
966  $code = substr($code, 0, 44);
967  } else {
968  $rest = '';
969  }
970  $t = '1'.$code;
971  do {
972  $d = bcmod($t, '900');
973  $t = bcdiv($t, '900');
974  array_unshift($cw, $d);
975  } while ($t != '0');
976  $code = $rest;
977  }
978  break;
979  }
980  case 913: { // Byte Compaction mode shift
981  $cw[] = ord($code);
982  break;
983  }
984  }
985  if ($addmode) {
986  // add the compaction mode codeword at the beginning
987  array_unshift($cw, $mode);
988  }
989  return $cw;
990  }
$rest
Definition: goto.php:46
$code
Definition: example_050.php:99
$s
Definition: pwgen.php:45
$i
Definition: disco.tpl.php:19
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
+ Here is the caller graph for this function:

◆ getErrorCorrection()

PDF417::getErrorCorrection (   $cw,
  $ecl 
)
protected

Returns the error correction codewords.

Parameters
$cw(array) array of codewords including Symbol Length Descriptor and pad
$ecl(int) error correction level 0-8
Returns
array of error correction codewords

Definition at line 780 of file pdf417.php.

References $d.

Referenced by __construct().

780  {
781  // get error correction coefficients
782  $ecc = $this->rsfactors[$ecl];
783  // number of error correction factors
784  $eclsize = (2 << $ecl);
785  // maximum index for $rsfactors[$ecl]
786  $eclmaxid = ($eclsize - 1);
787  // initialize array of error correction codewords
788  $ecw = array_fill(0, $eclsize, 0);
789  // for each data codeword
790  foreach($cw as $k => $d) {
791  $t1 = ($d + $ecw[$eclmaxid]) % 929;
792  for ($j = $eclmaxid; $j > 0; --$j) {
793  $t2 = ($t1 * $ecc[$j]) % 929;
794  $t3 = 929 - $t2;
795  $ecw[$j] = ($ecw[($j - 1)] + $t3) % 929;
796  }
797  $t2 = ($t1 * $ecc[0]) % 929;
798  $t3 = 929 - $t2;
799  $ecw[0] = $t3 % 929;
800  }
801  foreach($ecw as $j => $e) {
802  if ($e != 0) {
803  $ecw[$j] = 929 - $e;
804  }
805  }
806  $ecw = array_reverse($ecw);
807  return $ecw;
808  }
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
+ Here is the caller graph for this function:

◆ getErrorCorrectionLevel()

PDF417::getErrorCorrectionLevel (   $ecl,
  $numcw 
)
protected

Returns the error correction level (0-8) to be used.

Parameters
$ecl(int) error correction level
$numcw(int) number of data codewords
Returns
int error correction level

Definition at line 742 of file pdf417.php.

Referenced by __construct().

742  {
743  // get maximum correction level
744  $maxecl = 8; // starting error level
745  $maxerrsize = (928 - $numcw); // available codewords for error
746  while ($maxecl > 0) {
747  $errsize = (2 << $ecl);
748  if ($maxerrsize >= $errsize) {
749  break;
750  }
751  --$maxecl;
752  }
753  // check for automatic levels
754  if (($ecl < 0) OR ($ecl > 8)) {
755  if ($numcw < 41) {
756  $ecl = 2;
757  } elseif ($numcw < 161) {
758  $ecl = 3;
759  } elseif ($numcw < 321) {
760  $ecl = 4;
761  } elseif ($numcw < 864) {
762  $ecl = 5;
763  } else {
764  $ecl = $maxecl;
765  }
766  }
767  if ($ecl > $maxecl) {
768  $ecl = $maxecl;
769  }
770  return $ecl;
771  }
+ Here is the caller graph for this function:

◆ getInputSequences()

PDF417::getInputSequences (   $code)
protected

Create array of sequences from input.

Parameters
$code(string) code
Returns
bidimensional array containing characters and classification

Definition at line 816 of file pdf417.php.

References $code.

Referenced by __construct().

816  {
817  $sequence_array = array(); // array to be returned
818  $numseq = array();
819  // get numeric sequences
820  preg_match_all('/([0-9]{13,44})/', $code, $numseq, PREG_OFFSET_CAPTURE);
821  $numseq[1][] = array('', strlen($code));
822  $offset = 0;
823  foreach($numseq[1] as $seq) {
824  $seqlen = strlen($seq[0]);
825  if ($seq[1] > 0) {
826  // extract text sequence before the number sequence
827  $prevseq = substr($code, $offset, ($seq[1] - $offset));
828  $textseq = array();
829  // get text sequences
830  preg_match_all('/([\x09\x0a\x0d\x20-\x7e]{5,})/', $prevseq, $textseq, PREG_OFFSET_CAPTURE);
831  $textseq[1][] = array('', strlen($prevseq));
832  $txtoffset = 0;
833  foreach($textseq[1] as $txtseq) {
834  $txtseqlen = strlen($txtseq[0]);
835  if ($txtseq[1] > 0) {
836  // extract byte sequence before the text sequence
837  $prevtxtseq = substr($prevseq, $txtoffset, ($txtseq[1] - $txtoffset));
838  if (strlen($prevtxtseq) > 0) {
839  // add BYTE sequence
840  if ((strlen($prevtxtseq) == 1) AND ((count($sequence_array) > 0) AND ($sequence_array[(count($sequence_array) - 1)][0] == 900))) {
841  $sequence_array[] = array(913, $prevtxtseq);
842  } elseif ((strlen($prevtxtseq) % 6) == 0) {
843  $sequence_array[] = array(924, $prevtxtseq);
844  } else {
845  $sequence_array[] = array(901, $prevtxtseq);
846  }
847  }
848  }
849  if ($txtseqlen > 0) {
850  // add numeric sequence
851  $sequence_array[] = array(900, $txtseq[0]);
852  }
853  $txtoffset = $txtseq[1] + $txtseqlen;
854  }
855  }
856  if ($seqlen > 0) {
857  // add numeric sequence
858  $sequence_array[] = array(902, $seq[0]);
859  }
860  $offset = $seq[1] + $seqlen;
861  }
862  return $sequence_array;
863  }
$code
Definition: example_050.php:99
+ Here is the caller graph for this function:

Field Documentation

◆ $barcode_array

PDF417::$barcode_array = array()
protected

Barcode array to be returned which is readable by TCPDF.

Definition at line 99 of file pdf417.php.

Referenced by __construct(), and getBarcodeArray().

◆ $clusters

PDF417::$clusters
protected

Clusters of codewords (0, 3, 6)
Values are hex equivalents of binary representation of bars (1 = bar, 0 = space).


The codewords numbered from 900 to 928 have special meaning, some enable to switch between modes in order to optimise the code:

  • 900 : Switch to "Text" mode
  • 901 : Switch to "Byte" mode
  • 902 : Switch to "Numeric" mode
  • 903 - 912 : Reserved
  • 913 : Switch to "Octet" only for the next codeword
  • 914 - 920 : Reserved
  • 921 : Initialization
  • 922 : Terminator codeword for Macro PDF control block
  • 923 : Sequence tag to identify the beginning of optional fields in the Macro PDF control block
  • 924 : Switch to "Byte" mode (If the total number of byte is multiple of 6)
  • 925 : Identifier for a user defined Extended Channel Interpretation (ECI)
  • 926 : Identifier for a general purpose ECI format
  • 927 : Identifier for an ECI of a character set or code page
  • 928 : Macro marker codeword to indicate the beginning of a Macro PDF Control Block

Definition at line 156 of file pdf417.php.

◆ $rsfactors

PDF417::$rsfactors
protected

Array of factors of the Reed-Solomon polynomial equations used for error correction; one sub array for each correction level (0-8).

Definition at line 445 of file pdf417.php.

◆ $start_pattern

PDF417::$start_pattern = '11111111010101000'
protected

Start pattern.

Definition at line 105 of file pdf417.php.

◆ $stop_pattern

PDF417::$stop_pattern = '111111101000101001'
protected

Stop pattern.

Definition at line 111 of file pdf417.php.

◆ $textlatch

PDF417::$textlatch
protected
Initial value:
= array(
'01' => array(27), '02' => array(28), '03' => array(28,25),
'10' => array(28,28), '12' => array(28), '13' => array(28,25),
'20' => array(28), '21' => array(27), '23' => array(25),
'30' => array(29), '31' => array(29,27), '32' => array(29,28)
)

Array of switching codes for Text Compaction Sub-Modes.

Definition at line 128 of file pdf417.php.

◆ $textsubmodes

PDF417::$textsubmodes
protected
Initial value:
= array(
array(0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x20,0xFD,0xFE,0xFF),
array(0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x20,0xFD,0xFE,0xFF),
array(0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x26,0x0d,0x09,0x2c,0x3a,0x23,0x2d,0x2e,0x24,0x2f,0x2b,0x25,0x2a,0x3d,0x5e,0xFB,0x20,0xFD,0xFE,0xFF),
array(0x3b,0x3c,0x3e,0x40,0x5b,0x5c,0x5d,0x5f,0x60,0x7e,0x21,0x0d,0x09,0x2c,0x3a,0x0a,0x2d,0x2e,0x24,0x2f,0x22,0x7c,0x2a,0x28,0x29,0x3f,0x7b,0x7d,0x27,0xFF)
)

Array of text Compaction Sub-Modes (values 0xFB - 0xFF are used for submode changers).

Definition at line 117 of file pdf417.php.


The documentation for this class was generated from the following file: