Exemplo n.º 1
0
 /**
  * Construct a PDF417 barcode array
  * @param string $code The code to be represented by this barcode.
  * @param int $ecl error correction level (0-8); default -1 = automatic correction level
  * @param float $aspectratio the width to height of the symbol (excluding quiet zones)
  * @param array $macro information for macro block
  */
 function __construct($code, $ecl = -1, $aspectratio = 2.0, $macro = array())
 {
     parent::__construct($code);
     $this->barcode_array = array();
     if (is_null($code) or $code == '\\0' or $code == '') {
         return;
     }
     // get the input sequence array
     $sequence = $this->getInputSequences($code);
     $codewords = array();
     // array of code-words
     foreach ($sequence as $seq) {
         $cw = $this->getCompaction($seq[0], $seq[1], true);
         $codewords = array_merge($codewords, $cw);
     }
     if ($codewords[0] == 900) {
         // Text Alpha is the default mode, so remove the first code
         array_shift($codewords);
     }
     // count number of codewords
     $numcw = count($codewords);
     if ($numcw > 925) {
         // reached maximum data codeword capacity
         return;
     }
     // build macro control block codewords
     if (!empty($macro)) {
         $macrocw = array();
         // beginning of macro control block
         $macrocw[] = 928;
         // segment index
         $cw = $this->getCompaction(902, sprintf('%05d', $macro['segment_index']), false);
         $macrocw = array_merge($macrocw, $cw);
         // file ID
         $cw = $this->getCompaction(900, $macro['file_id'], false);
         $macrocw = array_merge($macrocw, $cw);
         // optional fields
         $optmodes = array(900, 902, 902, 900, 900, 902, 902);
         $optsize = array(-1, 2, 4, -1, -1, -1, 2);
         foreach ($optmodes as $k => $omode) {
             if (isset($macro['option_' . $k])) {
                 $macrocw[] = 923;
                 $macrocw[] = $k;
                 if ($optsize[$k] == 2) {
                     $macro['option_' . $k] = sprintf('%05d', $macro['option_' . $k]);
                 } elseif ($optsize[$k] == 4) {
                     $macro['option_' . $k] = sprintf('%010d', $macro['option_' . $k]);
                 }
                 $cw = $this->getCompaction($omode, $macro['option_' . $k], false);
                 $macrocw = array_merge($macrocw, $cw);
             }
         }
         if ($macro['segment_index'] == $macro['segment_total'] - 1) {
             // end of control block
             $macrocw[] = 922;
         }
         // update total codewords
         $numcw += count($macrocw);
     }
     // set error correction level
     $ecl = $this->getErrorCorrectionLevel($ecl, $numcw);
     // number of codewords for error correction
     $errsize = 2 << $ecl;
     // calculate number of columns (number of codewords per row) and rows
     $nce = $numcw + $errsize + 1;
     $cols = round((sqrt(4761 + 68 * $aspectratio * self::ROWHEIGHT * $nce) - 69) / 34);
     // adjust cols
     if ($cols < 1) {
         $cols = 1;
     } elseif ($cols > 30) {
         $cols = 30;
     }
     $rows = ceil($nce / $cols);
     $size = $cols * $rows;
     // adjust rows
     if ($rows < 3 or $rows > 90) {
         if ($rows < 3) {
             $rows = 3;
         } elseif ($rows > 90) {
             $rows = 90;
         }
         $cols = ceil($size / $rows);
         $size = $cols * $rows;
     }
     if ($size > 928) {
         // set dimensions to get maximum capacity
         if (abs($aspectratio - 17 * 29 / 32) < abs($aspectratio - 17 * 16 / 58)) {
             $cols = 29;
             $rows = 32;
         } else {
             $cols = 16;
             $rows = 58;
         }
         $size = 928;
     }
     // calculate padding
     $pad = $size - $nce;
     if ($pad > 0) {
         if ($size - $rows == $nce) {
             --$rows;
             $size -= $rows;
         } else {
             // add pading
             $codewords = array_merge($codewords, array_fill(0, $pad, 900));
         }
     }
     if (!empty($macro)) {
         // add macro section
         $codewords = array_merge($codewords, $macrocw);
     }
     // Symbol Lenght Descriptor (number of data codewords including Symbol Lenght Descriptor and pad codewords)
     $sld = $size - $errsize;
     // add symbol length description
     array_unshift($codewords, $sld);
     // calculate error correction
     $ecw = $this->getErrorCorrection($codewords, $ecl);
     // add error correction codewords
     $codewords = array_merge($codewords, $ecw);
     // add horizontal quiet zones to start and stop patterns
     $pstart = str_repeat('0', self::QUIETH) . $this->start_pattern;
     $pstop = $this->stop_pattern . str_repeat('0', self::QUIETH);
     $this->barcode_array['num_rows'] = $rows * self::ROWHEIGHT + 2 * self::QUIETV;
     $this->barcode_array['num_cols'] = ($cols + 2) * 17 + 35 + 2 * self::QUIETH;
     $this->barcode_array['bcode'] = array();
     // build rows for vertical quiet zone
     if (self::QUIETV > 0) {
         $empty_row = array_fill(0, $this->barcode_array['num_cols'], 0);
         for ($i = 0; $i < self::QUIETV; ++$i) {
             // add vertical quiet rows
             $this->barcode_array['bcode'][] = $empty_row;
         }
     }
     $k = 0;
     // codeword index
     $cid = 0;
     // initial cluster
     // for each row
     for ($r = 0; $r < $rows; ++$r) {
         // row start code
         $row = $pstart;
         switch ($cid) {
             case 0:
                 $L = 30 * intval($r / 3) + intval(($rows - 1) / 3);
                 break;
             case 1:
                 $L = 30 * intval($r / 3) + $ecl * 3 + ($rows - 1) % 3;
                 break;
             case 2:
                 $L = 30 * intval($r / 3) + ($cols - 1);
                 break;
         }
         // left row indicator
         $row .= sprintf('%17b', $this->clusters[$cid][$L]);
         // for each column
         for ($c = 0; $c < $cols; ++$c) {
             $row .= sprintf('%17b', $this->clusters[$cid][$codewords[$k]]);
             ++$k;
         }
         switch ($cid) {
             case 0:
                 $L = 30 * intval($r / 3) + ($cols - 1);
                 break;
             case 1:
                 $L = 30 * intval($r / 3) + intval(($rows - 1) / 3);
                 break;
             case 2:
                 $L = 30 * intval($r / 3) + $ecl * 3 + ($rows - 1) % 3;
                 break;
         }
         // right row indicator
         $row .= sprintf('%17b', $this->clusters[$cid][$L]);
         // row stop code
         $row .= $pstop;
         // convert the string to array
         $arow = preg_split('//', $row, -1, PREG_SPLIT_NO_EMPTY);
         // duplicate row to get the desired height
         for ($h = 0; $h < self::ROWHEIGHT; ++$h) {
             $this->barcode_array['bcode'][] = $arow;
         }
         ++$cid;
         if ($cid > 2) {
             $cid = 0;
         }
     }
     if (self::QUIETV > 0) {
         for ($i = 0; $i < self::QUIETV; ++$i) {
             // add vertical quiet rows
             $this->barcode_array['bcode'][] = $empty_row;
         }
     }
 }
Exemplo n.º 2
0
 /**
  * Construct a Data Matrix barcode array
  * @param string $code The code to be represented by this barcode.
  */
 function __construct($code)
 {
     parent::__construct($code);
     if (is_null($code) or $code == '\\0' or $code == '') {
         return;
     }
     // get data codewords
     $cw = $this->getHighLevelEncoding($code);
     // number of data codewords
     $nd = count($cw);
     // check size
     if ($nd > 1558) {
         return;
     }
     // get minimum required matrix size.
     foreach ($this->symbattr as $params) {
         if ($params[11] >= $nd) {
             break;
         }
     }
     if ($params[11] < $nd) {
         // too much data
         return;
     } elseif ($params[11] > $nd) {
         // add padding
         if ($this->last_enc == self::ENC_EDF) {
             // switch to ASCII encoding
             $cw[] = 124;
             ++$nd;
         } elseif ($this->last_enc != self::ENC_ASCII and $this->last_enc != self::ENC_BASE256) {
             // switch to ASCII encoding
             $cw[] = 254;
             ++$nd;
         }
         if ($params[11] > $nd) {
             // add first pad
             $cw[] = 129;
             ++$nd;
             // add remaining pads
             for ($i = $nd; $i <= $params[11]; ++$i) {
                 $cw[] = $this->get253StateCodeword(129, $i);
             }
         }
     }
     // add error correction codewords
     $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]);
     // get placement map
     $places = $this->getPlacemetMap($params[2], $params[3]);
     // fill the grid with data
     $grid = array();
     $i = 0;
     // region data row max index
     $rdri = $params[4] - 1;
     // region data column max index
     $rdci = $params[5] - 1;
     // for each vertical region
     for ($vr = 0; $vr < $params[9]; ++$vr) {
         // for each row on region
         for ($r = 0; $r < $params[4]; ++$r) {
             // get row
             $row = $vr * $params[4] + $r;
             // for each horizontal region
             for ($hr = 0; $hr < $params[8]; ++$hr) {
                 // for each column on region
                 for ($c = 0; $c < $params[5]; ++$c) {
                     // get column
                     $col = $hr * $params[5] + $c;
                     // braw bits by case
                     if ($r == 0) {
                         // top finder pattern
                         if ($c % 2) {
                             $grid[$row][$col] = 0;
                         } else {
                             $grid[$row][$col] = 1;
                         }
                     } elseif ($r == $rdri) {
                         // bottom finder pattern
                         $grid[$row][$col] = 1;
                     } elseif ($c == 0) {
                         // left finder pattern
                         $grid[$row][$col] = 1;
                     } elseif ($c == $rdci) {
                         // right finder pattern
                         if ($r % 2) {
                             $grid[$row][$col] = 1;
                         } else {
                             $grid[$row][$col] = 0;
                         }
                     } else {
                         // data bit
                         if ($places[$i] < 2) {
                             $grid[$row][$col] = $places[$i];
                         } else {
                             // codeword ID
                             $cw_id = floor($places[$i] / 10) - 1;
                             // codeword BIT mask
                             $cw_bit = pow(2, 8 - $places[$i] % 10);
                             $grid[$row][$col] = ($cw[$cw_id] & $cw_bit) == 0 ? 0 : 1;
                         }
                         ++$i;
                     }
                 }
             }
         }
     }
     $this->barcode_array['num_rows'] = $params[0];
     $this->barcode_array['num_cols'] = $params[1];
     $this->barcode_array['bcode'] = $grid;
 }