12
12
namespace chillerlan \QRCode \Decoder ;
13
13
14
14
use Throwable ;
15
- use chillerlan \QRCode \Common \{BitBuffer , EccLevel , Mode , ReedSolomonDecoder , Version };
15
+ use chillerlan \QRCode \Common \{BitBuffer , EccLevel , FormatInformation , Mode , ReedSolomonDecoder , Version };
16
16
use chillerlan \QRCode \Data \{AlphaNum , Byte , ECI , Kanji , Number };
17
17
use chillerlan \QRCode \Detector \Detector ;
18
18
use function count , array_fill , mb_convert_encoding , mb_detect_encoding ;
@@ -27,6 +27,10 @@ final class Decoder{
27
27
28
28
# private const GB2312_SUBSET = 1;
29
29
30
+ private ?Version $ version = null ;
31
+ private ?FormatInformation $ formatInfo = null ;
32
+ private EccLevel $ eccLevel ;
33
+
30
34
/**
31
35
* Decodes a QR Code represented as a BitMatrix.
32
36
* A 1 or "true" is taken to mean a black module.
@@ -70,22 +74,18 @@ public function decode(LuminanceSourceInterface $source):DecoderResult{
70
74
*/
71
75
private function decodeMatrix (BitMatrix $ bitMatrix ):DecoderResult {
72
76
// Read raw codewords
73
- $ rawCodewords = $ bitMatrix ->readCodewords ();
74
- $ version = $ bitMatrix ->getVersion ();
75
- $ formatInfo = $ bitMatrix ->getFormatInfo ();
77
+ $ rawCodewords = $ bitMatrix ->readCodewords ();
78
+ $ this -> version = $ bitMatrix ->getVersion ();
79
+ $ this -> formatInfo = $ bitMatrix ->getFormatInfo ();
76
80
77
- // technically this shouldn't happen as the respective read meathods would throw first
78
- if ($ version === null || $ formatInfo === null ){
79
- throw new QRCodeDecoderException ('unable to read version or ecc level ' );
81
+ if ($ this ->version === null || $ this ->formatInfo === null ){
82
+ throw new QRCodeDecoderException ('unable to read version or format info ' ); // @codeCoverageIgnore
80
83
}
81
84
82
- $ eccLevel = $ formatInfo ->getErrorCorrectionLevel ();
83
-
84
- // Separate into data blocks
85
- $ dataBlocks = $ this ->getDataBlocks ($ rawCodewords , $ version , $ eccLevel );
86
-
87
- $ resultBytes = [];
88
- $ resultOffset = 0 ;
85
+ $ this ->eccLevel = $ this ->formatInfo ->getErrorCorrectionLevel ();
86
+ $ dataBlocks = $ this ->getDataBlocks ($ rawCodewords );
87
+ $ resultBytes = [];
88
+ $ resultOffset = 0 ;
89
89
90
90
// Error-correct and copy data blocks together into a stream of bytes
91
91
foreach ($ dataBlocks as $ dataBlock ){
@@ -99,30 +99,24 @@ private function decodeMatrix(BitMatrix $bitMatrix):DecoderResult{
99
99
}
100
100
101
101
// Decode the contents of that stream of bytes
102
- return $ this ->decodeBitStream ($ resultBytes, $ version , $ eccLevel );
102
+ return $ this ->decodeBitStream ($ resultBytes );
103
103
}
104
104
105
105
/**
106
106
* When QR Codes use multiple data blocks, they are actually interleaved.
107
107
* That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
108
108
* method will separate the data into original blocks.
109
109
*
110
- * @param array $rawCodewords bytes as read directly from the QR Code
111
- * @param \chillerlan\QRCode\Common\Version $version version of the QR Code
112
- * @param \chillerlan\QRCode\Common\EccLevel $eccLevel error-correction level of the QR Code
110
+ * @param array $rawCodewords bytes as read directly from the QR Code
113
111
*
114
112
* @return array DataBlocks containing original bytes, "de-interleaved" from representation in the QR Code
115
113
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
116
114
*/
117
- private function getDataBlocks (array $ rawCodewords , Version $ version , EccLevel $ eccLevel ):array {
118
-
119
- if (count ($ rawCodewords ) !== $ version ->getTotalCodewords ()){
120
- throw new QRCodeDecoderException ('$rawCodewords differ from total codewords for version ' );
121
- }
115
+ private function getDataBlocks (array $ rawCodewords ):array {
122
116
123
117
// Figure out the number and size of data blocks used by this version and
124
118
// error correction level
125
- [$ numEccCodewords , $ eccBlocks ] = $ version ->getRSBlocks ($ eccLevel );
119
+ [$ numEccCodewords , $ eccBlocks ] = $ this -> version ->getRSBlocks ($ this -> eccLevel );
126
120
127
121
// Now establish DataBlocks of the appropriate size and number of data codewords
128
122
$ result = [];//new DataBlock[$totalBlocks];
@@ -210,11 +204,11 @@ private function correctErrors(array $codewordBytes, int $numDataCodewords):arra
210
204
/**
211
205
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
212
206
*/
213
- private function decodeBitStream (array $ bytes, Version $ version , EccLevel $ ecLevel ):DecoderResult {
207
+ private function decodeBitStream (array $ bytes ):DecoderResult {
214
208
$ bits = new BitBuffer ($ bytes );
215
209
$ symbolSequence = -1 ;
216
210
$ parityData = -1 ;
217
- $ versionNumber = $ version ->getVersionNumber ();
211
+ $ versionNumber = $ this -> version ->getVersionNumber ();
218
212
219
213
$ result = '' ;
220
214
$ eciCharset = null ;
@@ -319,8 +313,9 @@ private function decodeBitStream(array $bytes, Version $version, EccLevel $ecLev
319
313
return new DecoderResult ([
320
314
'rawBytes ' => $ bytes ,
321
315
'data ' => $ result ,
322
- 'version ' => $ version ,
323
- 'eccLevel ' => $ ecLevel ,
316
+ 'version ' => $ this ->version ,
317
+ 'eccLevel ' => $ this ->eccLevel ,
318
+ 'maskPattern ' => $ this ->formatInfo ->getMaskPattern (),
324
319
'structuredAppendParity ' => $ parityData ,
325
320
'structuredAppendSequence ' => $ symbolSequence
326
321
]);
0 commit comments