Example #1
0
 public static function encode($content, $eccPercent = self::DEFAULT_EC_PERCENT, $dataEncoder = null)
 {
     if (strlen($content) == 0) {
         throw new \InvalidArgumentException('No content provided');
     }
     if (null === $dataEncoder) {
         $dataEncoder = new DynamicDataEncoder();
     } elseif (!$dataEncoder instanceof DataEncoderInterface) {
         throw new \InvalidArgumentException('dataEncoder has to implement DataEncoderInterface');
     }
     $bits = $dataEncoder->encode($content);
     $eccBits = intval($bits->getLength() * $eccPercent / 100 + 11);
     $totalSizeBits = $bits->getLength() + $eccBits;
     $layers = 0;
     $wordSize = 0;
     $totalSymbolBits = 0;
     $stuffedBits = null;
     for ($layers = 1; $layers < self::LAYERS_COMPACT; $layers++) {
         if (self::getBitsPerLayer($layers, false) >= $totalSizeBits) {
             if ($wordSize != self::$wordSize[$layers]) {
                 $wordSize = self::$wordSize[$layers];
                 $stuffedBits = self::stuffBits($bits, $wordSize);
             }
             $totalSymbolBits = self::getBitsPerLayer($layers, false);
             if ($stuffedBits->getLength() + $eccBits <= $totalSymbolBits) {
                 break;
             }
         }
     }
     $compact = true;
     if ($layers == self::LAYERS_COMPACT) {
         $compact = false;
         for ($layers = 1; $layers < self::LAYERS_FULL; $layers++) {
             if (self::getBitsPerLayer($layers, true) >= $totalSizeBits) {
                 if ($wordSize != self::$wordSize[$layers]) {
                     $wordSize = self::$wordSize[$layers];
                     $stuffedBits = self::stuffBits($bits, $wordSize);
                 }
                 $totalSymbolBits = self::getBitsPerLayer($layers, true);
                 if ($stuffedBits->getLength() + $eccBits <= $totalSymbolBits) {
                     break;
                 }
             }
         }
     }
     if ($layers == self::LAYERS_FULL) {
         throw new \InvalidArgumentException('Data too large');
     }
     $messageSizeInWords = intval(($stuffedBits->getLength() + $wordSize - 1) / $wordSize);
     for ($i = $messageSizeInWords * $wordSize - $stuffedBits->getLength(); $i > 0; $i--) {
         $stuffedBits->append(1);
     }
     // generate check words
     $rs = new ReedSolomonEncoder(self::getGF($wordSize));
     $totalSizeInFullWords = intval($totalSymbolBits / $wordSize);
     $messageWords = self::bitsToWords($stuffedBits, $wordSize, $totalSizeInFullWords);
     $messageWords = $rs->encodePadded($messageWords, $totalSizeInFullWords - $messageSizeInWords);
     // convert to bit array and pad in the beginning
     $startPad = $totalSymbolBits % $wordSize;
     $messageBits = new BitArray();
     $messageBits->append(0, $startPad);
     foreach ($messageWords as $messageWord) {
         $messageBits->append($messageWord, $wordSize);
     }
     // generate mode message
     $modeMessage = self::generateModeMessage($compact, $layers, $messageSizeInWords);
     // allocate symbol
     if ($compact) {
         $matrixSize = $baseMatrixSize = 11 + $layers * 4;
         $alignmentMap = array();
         for ($i = 0; $i < $matrixSize; $i++) {
             $alignmentMap[] = $i;
         }
     } else {
         $baseMatrixSize = 14 + $layers * 4;
         $matrixSize = $baseMatrixSize + 1 + 2 * intval((intval($baseMatrixSize / 2) - 1) / 15);
         $alignmentMap = array_fill(0, $baseMatrixSize, 0);
         $origCenter = intval($baseMatrixSize / 2);
         $center = intval($matrixSize / 2);
         for ($i = 0; $i < $origCenter; $i++) {
             $newOffset = $i + intval($i / 15);
             $alignmentMap[$origCenter - $i - 1] = $center - $newOffset - 1;
             $alignmentMap[$origCenter + $i] = $center + $newOffset + 1;
         }
     }
     $matrix = new BitMatrix($matrixSize);
     // draw mode and data bits
     for ($i = 0, $rowOffset = 0; $i < $layers; $i++) {
         if ($compact) {
             $rowSize = ($layers - $i) * 4 + 9;
         } else {
             $rowSize = ($layers - $i) * 4 + 12;
         }
         for ($j = 0; $j < $rowSize; $j++) {
             $columnOffset = $j * 2;
             for ($k = 0; $k < 2; $k++) {
                 if ($messageBits->get($rowOffset + $columnOffset + $k)) {
                     $matrix->set($alignmentMap[$i * 2 + $k], $alignmentMap[$i * 2 + $j]);
                 }
                 if ($messageBits->get($rowOffset + $rowSize * 2 + $columnOffset + $k)) {
                     $matrix->set($alignmentMap[$i * 2 + $j], $alignmentMap[$baseMatrixSize - 1 - $i * 2 - $k]);
                 }
                 if ($messageBits->get($rowOffset + $rowSize * 4 + $columnOffset + $k)) {
                     $matrix->set($alignmentMap[$baseMatrixSize - 1 - $i * 2 - $k], $alignmentMap[$baseMatrixSize - 1 - $i * 2 - $j]);
                 }
                 if ($messageBits->get($rowOffset + $rowSize * 6 + $columnOffset + $k)) {
                     $matrix->set($alignmentMap[$baseMatrixSize - 1 - $i * 2 - $j], $alignmentMap[$i * 2 + $k]);
                 }
             }
         }
         $rowOffset += $rowSize * 8;
     }
     $matrix = self::drawModeMessage($matrix, $compact, $matrixSize, $modeMessage);
     // draw alignment marks
     if ($compact) {
         $matrix = self::drawBullsEye($matrix, intval($matrixSize / 2), 5);
     } else {
         $matrix = self::drawBullsEye($matrix, intval($matrixSize / 2), 7);
         for ($i = 0, $j = 0; $i < intval($baseMatrixSize / 2) - 1; $i += 15, $j += 16) {
             for ($k = intval($matrixSize / 2) & 1; $k < $matrixSize; $k += 2) {
                 $matrix->set(intval($matrixSize / 2) - $j, $k);
                 $matrix->set(intval($matrixSize / 2) + $j, $k);
                 $matrix->set($k, intval($matrixSize / 2) - $j);
                 $matrix->set($k, intval($matrixSize / 2) + $j);
             }
         }
     }
     $code = new AztecCode();
     $code->setCompact($compact);
     $code->setSize($matrixSize);
     $code->setLayers($layers);
     $code->setCodeWords($messageSizeInWords);
     $code->setMatrix($matrix);
     return $code;
 }
Example #2
0
 private function encodeBitCountTest($data, $expectedBitCount)
 {
     $encoder = new DynamicDataEncoder();
     $bits = $encoder->encode($data);
     $this->assertEquals($expectedBitCount, $bits->getLength());
 }