diff --git a/src/Common/ReedSolomonDecoder.php b/src/Common/ReedSolomonDecoder.php index 3762c7011..5872d6aee 100644 --- a/src/Common/ReedSolomonDecoder.php +++ b/src/Common/ReedSolomonDecoder.php @@ -34,6 +34,48 @@ use function array_fill, array_reverse, count; */ final class ReedSolomonDecoder{ + /** + * Error-correct and copy data blocks together into a stream of bytes + */ + public function decode(array $dataBlocks):array{ + $resultBytes = []; + + foreach($dataBlocks as $dataBlock){ + [$numDataCodewords, $codewordBytes] = $dataBlock; + + $corrected = $this->correctErrors($codewordBytes, $numDataCodewords); + + for($i = 0; $i < $numDataCodewords; $i++){ + $resultBytes[] = $corrected[$i]; + } + } + + return $resultBytes; + } + + /** + * Given data and error-correction codewords received, possibly corrupted by errors, attempts to + * correct the errors in-place using Reed-Solomon error correction. + */ + private function correctErrors(array $codewordBytes, int $numDataCodewords):array{ + // First read into an array of ints + $codewordsInts = []; + + foreach($codewordBytes as $codewordByte){ + $codewordsInts[] = $codewordByte & 0xFF; + } + + $decoded = $this->decodeWords($codewordsInts, (count($codewordBytes) - $numDataCodewords)); + + // Copy back into array of bytes -- only need to worry about the bytes that were data + // We don't care about errors in the error-correction codewords + for($i = 0; $i < $numDataCodewords; $i++){ + $codewordBytes[$i] = $decoded[$i]; + } + + return $codewordBytes; + } + /** * Decodes given set of received codewords, which include both data and error-correction * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, @@ -45,7 +87,7 @@ final class ReedSolomonDecoder{ * @return int[] * @throws \RuntimeException if decoding fails for any reason */ - public function decode(array $received, int $numEccCodewords):array{ + private function decodeWords(array $received, int $numEccCodewords):array{ $poly = new GenericGFPoly($received); $syndromeCoefficients = []; $error = false; diff --git a/src/Decoder/Decoder.php b/src/Decoder/Decoder.php index 5abe401b3..8ddcb1feb 100644 --- a/src/Decoder/Decoder.php +++ b/src/Decoder/Decoder.php @@ -83,21 +83,7 @@ final class Decoder{ } $this->eccLevel = $this->formatInfo->getErrorCorrectionLevel(); - $dataBlocks = $this->getDataBlocks($rawCodewords); - $resultBytes = []; - $resultOffset = 0; - - // Error-correct and copy data blocks together into a stream of bytes - foreach($dataBlocks as $dataBlock){ - [$numDataCodewords, $codewordBytes] = $dataBlock; - - $corrected = $this->correctErrors($codewordBytes, $numDataCodewords); - - for($i = 0; $i < $numDataCodewords; $i++){ - $resultBytes[$resultOffset++] = $corrected[$i]; - } - } - + $resultBytes = (new ReedSolomonDecoder)->decode($this->getDataBlocks($rawCodewords)); // Decode the contents of that stream of bytes return $this->decodeBitStream($resultBytes); } @@ -178,29 +164,6 @@ final class Decoder{ return $result; } - /** - * Given data and error-correction codewords received, possibly corrupted by errors, attempts to - * correct the errors in-place using Reed-Solomon error correction. - */ - private function correctErrors(array $codewordBytes, int $numDataCodewords):array{ - // First read into an array of ints - $codewordsInts = []; - - foreach($codewordBytes as $i => $codewordByte){ - $codewordsInts[$i] = $codewordByte & 0xFF; - } - - $decoded = (new ReedSolomonDecoder)->decode($codewordsInts, (count($codewordBytes) - $numDataCodewords)); - - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for($i = 0; $i < $numDataCodewords; $i++){ - $codewordBytes[$i] = $decoded[$i]; - } - - return $codewordBytes; - } - /** * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException */