Ejemplo n.º 1
0
 /**
  * Encodes "content" with the error correction level "ecLevel".
  *
  * @param  string               $content
  * @param  ErrorCorrectionLevel $ecLevel
  * @param  ?                    $hints
  * @return QrCode
  */
 public static function encode($content, ErrorCorrectionLevel $ecLevel, $encoding = self::DEFAULT_BYTE_MODE_ECODING)
 {
     // Pick an encoding mode appropriate for the content. Note that this
     // will not attempt to use multiple modes / segments even if that were
     // more efficient. Would be nice.
     $mode = self::chooseMode($content, $encoding);
     //debug($mode->get());
     // This will store the header information, like mode and length, as well
     // as "header" segments like an ECI segment.
     $headerBits = new BitArray();
     // Append ECI segment if applicable
     if ($mode->get() === Mode::BYTE && $encoding !== self::DEFAULT_BYTE_MODE_ECODING) {
         $eci = CharacterSetEci::getCharacterSetEciByName($encoding);
         if ($eci !== null) {
             self::appendEci($eci, $headerBits);
         }
     }
     // (With ECI in place,) Write the mode marker
     self::appendModeInfo($mode, $headerBits);
     // Collect data within the main segment, separately, to count its size
     // if needed. Don't add it to main payload yet.
     $dataBits = new BitArray();
     self::appendBytes($content, $mode, $dataBits, $encoding);
     // Hard part: need to know version to know how many bits length takes.
     // But need to know how many bits it takes to know version. First we
     // take a guess at version by assuming version will be the minimum, 1:
     $provisionalBitsNeeded = $headerBits->getSize() + $mode->getCharacterCountBits(Version::getVersionForNumber(1)) + $dataBits->getSize();
     $provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel);
     // Use that guess to calculate the right version. I am still not sure
     // this works in 100% of cases.
     $bitsNeeded = $headerBits->getSize() + $mode->getCharacterCountBits($provisionalVersion) + $dataBits->getSize();
     $version = self::chooseVersion($bitsNeeded, $ecLevel);
     $headerAndDataBits = new BitArray();
     $headerAndDataBits->appendBitArray($headerBits);
     // Find "length" of main segment and write it.
     $numLetters = $mode->get() === Mode::BYTE ? $dataBits->getSizeInBytes() : strlen($content);
     self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits);
     // Put data together into the overall payload.
     $headerAndDataBits->appendBitArray($dataBits);
     $ecBlocks = $version->getEcBlocksForLevel($ecLevel);
     $numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords();
     // Terminate the bits properly.
     self::terminateBits($numDataBytes, $headerAndDataBits);
     // Interleave data bits with error correction code.
     $finalBits = self::interleaveWithEcBytes($headerAndDataBits, $version->getTotalCodewords(), $numDataBytes, $ecBlocks->getNumBlocks());
     $qrCode = new QrCode();
     $qrCode->setErrorCorrectionLevel($ecLevel);
     $qrCode->setMode($mode);
     $qrCode->setVersion($version);
     // Choose the mask pattern and set to "qrCode".
     $dimension = $version->getDimensionForVersion();
     $matrix = new ByteMatrix($dimension, $dimension);
     $maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix);
     $qrCode->setMaskPattern($maskPattern);
     // Build the matrix and set it to "qrCode".
     MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix);
     $qrCode->setMatrix($matrix);
     return $qrCode;
 }