| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace Zxing\Qrcode\Decoder; |
|
|
| use Zxing\ChecksumException; |
| use Zxing\DecodeHintType; |
| use Zxing\FormatException; |
| use Zxing\Common\BitMatrix; |
| use Zxing\Common\DecoderResult; |
| use Zxing\Common\Reedsolomon\GenericGF; |
| use Zxing\Common\Reedsolomon\ReedSolomonDecoder; |
| use Zxing\Common\Reedsolomon\ReedSolomonException; |
|
|
| |
| |
| |
| |
| |
| |
| final class Decoder |
| { |
|
|
| private $rsDecoder; |
|
|
| public function __construct() |
| { |
| $this->rsDecoder = new ReedSolomonDecoder(GenericGF::$QR_CODE_FIELD_256); |
| } |
|
|
| public function decode($variable, $hints = null) |
| { |
| if (is_array($variable)) { |
| return $this->decodeImage($variable, $hints); |
| } elseif ($variable instanceof BitMatrix) { |
| return $this->decodeBits($variable, $hints); |
| } elseif ($variable instanceof BitMatrixParser) { |
| return $this->decodeParser($variable, $hints); |
| } |
| die('decode error Decoder.php'); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function decodeImage($image, $hints = null) |
| { |
| $dimension = count($image); |
| $bits = new BitMatrix($dimension); |
| for ($i = 0; $i < $dimension; $i++) { |
| for ($j = 0; $j < $dimension; $j++) { |
| if ($image[$i][$j]) { |
| $bits->set($j, $i); |
| } |
| } |
| } |
|
|
| return $this->decode($bits, $hints); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function decodeBits($bits, $hints = null) |
| { |
|
|
| |
| $parser = new BitMatrixParser($bits); |
| $fe = null; |
| $ce = null; |
| try { |
| return $this->decode($parser, $hints); |
| } catch (FormatException $e) { |
| $fe = $e; |
| } catch (ChecksumException $e) { |
| $ce = $e; |
| } |
|
|
| try { |
|
|
| |
| $parser->remask(); |
|
|
| |
| $parser->setMirror(true); |
|
|
| |
| $parser->readVersion(); |
|
|
| |
| $parser->readFormatInformation(); |
|
|
| |
| |
| |
| |
| |
| |
| |
| $parser->mirror(); |
|
|
| $result = $this->decode($parser, $hints); |
|
|
| |
| $result->setOther(new QRCodeDecoderMetaData(true)); |
|
|
| return $result; |
|
|
| } catch (FormatException $e) { |
| |
| if ($fe != null) { |
| throw $fe; |
| } |
| if ($ce != null) { |
| throw $ce; |
| } |
| throw $e; |
|
|
| } |
| } |
|
|
| private function decodeParser($parser, $hints = null) |
| { |
| $version = $parser->readVersion(); |
| $ecLevel = $parser->readFormatInformation()->getErrorCorrectionLevel(); |
|
|
| |
| $codewords = $parser->readCodewords(); |
| |
| $dataBlocks = DataBlock::getDataBlocks($codewords, $version, $ecLevel); |
|
|
| |
| $totalBytes = 0; |
| foreach ($dataBlocks as $dataBlock) { |
| $totalBytes += $dataBlock->getNumDataCodewords(); |
| } |
| $resultBytes = fill_array(0, $totalBytes, 0); |
| $resultOffset = 0; |
|
|
| |
| foreach ($dataBlocks as $dataBlock) { |
| $codewordBytes = $dataBlock->getCodewords(); |
| $numDataCodewords = $dataBlock->getNumDataCodewords(); |
| $this->correctErrors($codewordBytes, $numDataCodewords); |
| for ($i = 0; $i < $numDataCodewords; $i++) { |
| $resultBytes[$resultOffset++] = $codewordBytes[$i]; |
| } |
| } |
|
|
| |
| return DecodedBitStreamParser::decode($resultBytes, $version, $ecLevel, $hints); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function correctErrors(&$codewordBytes, $numDataCodewords) |
| { |
| $numCodewords = count($codewordBytes); |
| |
| $codewordsInts = fill_array(0, $numCodewords, 0); |
| for ($i = 0; $i < $numCodewords; $i++) { |
| $codewordsInts[$i] = $codewordBytes[$i] & 0xFF; |
| } |
| $numECCodewords = count($codewordBytes) - $numDataCodewords; |
| try { |
| $this->rsDecoder->decode($codewordsInts, $numECCodewords); |
| } catch (ReedSolomonException $ignored) { |
| throw ChecksumException::getChecksumInstance(); |
| } |
| |
| |
| for ($i = 0; $i < $numDataCodewords; $i++) { |
| $codewordBytes[$i] = $codewordsInts[$i]; |
| } |
| } |
| } |
|
|